# enterprise-enquiry Worker

Backend for the enquiry form on `/experiences/enterprise`. The static page
POSTs the form here; the Worker verifies **Cloudflare Turnstile** server-side
(plus honeypot + minimum-fill-time), then imports the enquiry into **Front's
support@bigscreenvr.com inbox** via the message-import API. It arrives as a
normal open conversation FROM the submitter, subject
`Enterprise page enquiry — …`, body a formatted card with all fields —
so the team replies in Front and the answer emails the customer like any
other ticket. No sending domain, no DNS changes, no extra vendor.

Until this Worker is deployed and the page is given its keys, the form keeps
its old behavior (composes a prefilled mailto to support@). Any failure after
deploy also falls back to mailto, so an outage never eats an enquiry.

## One-time setup

### 1. Turnstile widget (Cloudflare dashboard → Turnstile)

- Create a widget, mode **Managed**.
- Hostnames: `bigscreenvr.com`, `www.bigscreenvr.com`, the Pages project's
  `*.pages.dev` hostname, `dev-website.bigscreencloud.com` (staging), and
  `localhost` for testing. Turnstile enforces this list, so a hostname missing
  here fails the challenge before the POST is ever made and the page silently
  drops to its mailto fallback. Keep it in step with `ALLOWED_ORIGINS` in
  `wrangler.toml` — the two lists gate the same surfaces.
- Note the **site key** (public, goes in the page) and **secret key**
  (goes in this Worker).

### 2. Front API token + inbox id

- In Front: Settings → Developers → API tokens → create a token with the
  **Shared resources** scope (needs `messages:write`).
- Find the support inbox id (`inb_…`):

  ```bash
  curl -s https://api2.frontapp.com/inboxes -H "Authorization: Bearer <token>"
  ```

- Put the inbox id in `wrangler.toml` → `FRONT_INBOX_ID`.

### 3. Deploy

```bash
npx wrangler deploy
npx wrangler secret put TURNSTILE_SECRET
npx wrangler secret put FRONT_API_TOKEN
```

Note the deployed URL (`https://enterprise-enquiry.<subdomain>.workers.dev`).

### 4. Point the page at it

In `src/site/pages/enterprise.html`, on the `<form id="biz-enquiry">` tag,
fill in:

```html
data-endpoint="https://enterprise-enquiry.<subdomain>.workers.dev"
data-turnstile-sitekey="<site key from step 1>"
```

then rebuild (`node scripts/build-pages.mjs`). With either attribute empty
the page stays on the mailto path.

## How it lands in Front

The import is flagged `is_inbound: true`, `is_archived: false` (opens as a
live conversation, not buried in history), `should_skip_rules: false` (your
routing rules and tags run on it). Sender handle is the customer's email, so
threading and replies behave exactly like inbound mail. `external_id` is a
random UUID per submission, so retries can't duplicate.

## Bot defenses (layered)

1. **Turnstile, verified server-side** — the page runs an invisible managed
   challenge at submit time (`execution: "execute"`, interaction-only, so
   humans normally see nothing); the Worker calls `siteverify` with the
   secret. No token or a failed verdict → 403.
2. **Honeypot** — hidden `website` field; if filled, the Worker returns a
   fake success and sends nothing.
3. **Minimum fill time** — the page reports ms since page load; under 3s →
   fake success, nothing sent.
4. **Field caps + CORS** — oversized payloads rejected; only site origins
   (prod domains, `*.pages.dev`, localhost) may call the Worker.

## Testing

After deploy, from the repo root: serve the built site locally
(`node scripts/mock-server.mjs` or the dev server), open
`/experiences/enterprise`, submit the form, and check the Front support
inbox for "Enterprise page enquiry". A quick bot-path check: POST with the
`website` field filled — expect `{"ok":true}` and no conversation created.
