# Go-Live Checklist

Work through the checklist, then run the four tests. The examples use `octet.example.com` for your edge and `www.example.com` for your site.

## Checklist

**Edge**

- [ ] The edge runs on its own hostname, with a DNS record pointing straight at the host or at a passthrough layer 4 load balancer. See [Deploy the Edge](/docs/browser/integration/deploy-edge/).
- [ ] No proxy, application load balancer or CDN terminates TCP or TLS in front of the edge.
- [ ] `https://octet.example.com/health` returns `{"ok":true,"role":"octet-edge"}`.
- [ ] The license check below returns `unsealed_bundle`.
- [ ] The edge binary matches its checksum in the release's `SHA256SUMS`, and your deployment records note the version and checksum you installed.
- [ ] `EDGE_CLIENT_CERT_FILE` and `EDGE_CLIENT_KEY_FILE` point at the certificate issued for this host in the portal's **Edge certificates** tab and its key, and the key is readable only by root and the `octet-edge` group.
- [ ] `ALLOWED_ORIGIN` lists exactly the origins that load the collector.
- [ ] `EDGE_DEBUG`, `EDGE_EXPOSE_VERDICT` and `EXIT_IP` are unset. See [Edge Configuration](/docs/browser/reference/edge-config/).
- [ ] Certificate renewal restarts the edge. Check with `sudo certbot renew --dry-run --run-deploy-hooks`.

**Page**

- [ ] You serve `octet-collector.js` v1.3.0 from your own origin with its `integrity` hash, or install the v1.3.0 package tarball from the release.
- [ ] Your Content Security Policy allows the hosts for your mode and `worker-src blob:`. See [Network and CSP](/docs/browser/reference/network/).
- [ ] Each page view gets a new random `sessionRef`, created and stored on your backend.
- [ ] `start()` runs at page load, and `ready()` runs at the moment of action.

**Backend**

- [ ] The read token comes from your secret store, never from code.
- [ ] Your HTTP client's timeout is longer than `waitMs`.
- [ ] Your policy says what happens when the fetch returns `404`.
- [ ] Your policy acts on `alarm` of `medium` or above, as well as on `country`. See [Verdicts](/docs/browser/concepts/verdicts/).
- [ ] If you store verdicts, you verify and store the `token`, and keep a copy of each Octet key you verify with. See [Keep Verdicts for Audit](/docs/browser/integration/keep-verdicts/).

**Operations**

- [ ] Your calendar has reminders before the read token expires, before the edge's client certificate expires, and before the license token's 365 days are up.
- [ ] Your privacy notice covers the data in [Privacy and Data](/docs/browser/concepts/privacy/).

## License check

This request proves that your edge can reach Octet, and that Octet accepts your license token and your edge's client certificate. It sends an empty body, which Octet refuses only after it has checked both:

```bash
curl -s -X POST https://octet.example.com/v1/signals -H 'content-type: application/json' -d '{}'
```

With a valid license token and client certificate, the response is `400`, because an empty body isn't a sealed collection:

```json
{"error":"octet_rejected","reason":"unsealed_bundle","status":400}
```

A `401` or `403` with a different `reason` means the license or the client certificate was refused. See [Errors](/docs/browser/reference/errors/).

## Test 1: an honest session

1. On a normal connection with no VPN, open a page that runs the collector.
2. Trigger the action that calls `ready()`.
3. On your backend, fetch the verdict for that `sessionRef`.

**Expect:** `200`, `country` set to the country you are in, and `alarm` of `none`. A `low` alarm is also normal, for example when your device is set up for another country. Verify the `token` with the code from [Verify the Signed Token](/docs/browser/integration/verify-token/) and check that it passes.

## Test 2: a session through a VPN

1. Connect to a commercial VPN that exits in a different country from the one you are in.
2. Repeat test 1 in the default `full` mode.

**Expect:** `alarm` of `medium` or `high`. Octet does not flag every masked session. If a VPN session keeps coming back as `none`, check that nothing terminates TCP or TLS in front of your edge, and that the page is running in `full` mode.

## Test 3: an expired or revoked token

1. In the portal's **Read tokens** tab, create a 30-day read token, then revoke it.
2. Wait a few minutes, then fetch a verdict with it.

**Expect:** `401` with `{"error":"revoked"}`. An expired read token gets `{"error":"expired"}`, and your backend should handle both the same way: alert, and switch to a live token.

To test an expired verdict token, run the `expired` case from [Test the examples](/docs/browser/integration/verify-token/#test-the-examples). Your verifier must reject it.

## Test 4: a rejected license

Run this on a test edge, never on your production edge.

1. Set `LICENSE=octet_live_invalid` in the edge's environment file and restart the edge.
2. Run the license check above.
3. Load a page that runs the collector against this edge.

**Expect:** the license check returns `401` with `"reason":"malformed_token"`. In the browser, `ready()` rejects with `signal report failed: 401`. Your backend's fetch for that `sessionRef` returns `404`, because no verdict was produced.

Restore the real license token and restart the edge when you are done.
