# Release smoke test

Run this on a **clean Chrome profile** (Settings → Profiles → Add → New)
before announcing a new build. Anything that can fail silently lives in
this list.

Roughly 15 minutes start to finish.

## 0. Prerequisites

- [ ] `npm run build` from `statisticasino/` finished without errors.
      This rebuilds `static/downloads/casino-inspector.zip` from the
      current `casinoMalwareExtension/` tree (the prebuild script does
      it automatically) and produces the production server bundle.
- [ ] The website is running somewhere reachable (locally with
      `node build`, or on its real production host). Note the URL.
- [ ] `casinoMalwareExtension/serialize.js`'s `FLUSH_ENDPOINT` and
      `casinoMalwareExtension/manifest.json`'s `host_permissions` both
      point at that same URL. **If either still says
      `statisticasino.example.com`, stop and fix it before continuing.**
      The current production URL is
      `https://www.sinostatistica.net/api/flush` (TLS terminated by
      Cloudflare → origin nginx). `host_permissions` lists both
      `https://www.sinostatistica.net/*` and `https://sinostatistica.net/*`
      so the SW's fetch authorises whichever form `FLUSH_ENDPOINT`
      ends up using.
- [ ] Manifest `version` was bumped since the last release (otherwise
      Chrome aggressively caches the old icon).

## 1. Install via the contribute page

- [ ] In a fresh Chrome profile with no extensions, navigate to
      `<site>/contribute`.
- [ ] Click "Download .zip". Confirm the download is named
      `casino-inspector.zip` and is a few MB.
- [ ] Unzip into a folder you'll remember.
- [ ] Open `chrome://extensions`, toggle Developer mode on, click
      "Load unpacked", select the unzipped folder.
- [ ] Confirm the extension appears with the new name (NOT
      "Casino.org Inspector (Dev)").
- [ ] Confirm the toolbar icon shows the **two-card** branding
      (Ace of Hearts overlapping a card back), not the puzzle-piece
      placeholder. Pin the extension so the icon stays visible.

If the icon shows the puzzle piece for more than ~10 seconds after
install, something went wrong with the icon files. Check
`icons/icon32.png` exists in the unzipped folder and that
`manifest.json` references it.

## 2. Capture a hand

- [ ] Open `https://www.casino.org/replaypoker/play/...`. Sit at any
      table and play (or watch) one full hand.
- [ ] Click the extension icon. The Game History tab opens.
- [ ] Confirm: at least one Player → Table → Round row exists.
- [ ] Click the round to expand the inline replay. Confirm the felt
      diagram, scrubber, and Prev/Next buttons all work.
- [ ] Confirm your seat is highlighted in red (perspective-owner).

## 3. Selection / action panel

- [ ] Click the parent checkbox at the table level. Confirm every
      child round becomes ticked, and the table parent becomes "all".
- [ ] Click one round-level checkbox to untick it. Confirm the table
      parent goes to "some" (the `-` indeterminate visual).
- [ ] Click "Cancel" in the action panel. Confirm everything clears.
- [ ] Click "Select all". Confirm every checkbox in every player /
      table / round is "all".

## 4. Flush

- [ ] With a non-empty selection, click "Flush now".
- [ ] Confirm the Sync card transitions to "flushing", then either
      "flushed" (success) or surfaces a readable error message.
- [ ] Auto-flush smoke test: in extension Settings, leave
      "Auto-flush on every finishHand" on, capture one finished hand,
      and within ~2 seconds of the hand ending the SW console should
      log a line starting `[CASINO] autoflush: reason=finishHand`.
      The Sync card's `pending` count should be at 0 the next time
      you open History.
- [ ] Auto-delete smoke test: tick "Auto-delete after flush" in
      Settings → Sync, capture another finished hand, wait for the
      autoflush log line, then refresh History. The just-flushed
      round should be gone; `Storage → Captured messages` should
      have dropped accordingly. Already-flushed audit rows survive
      (visible only via `chrome.storage.local`'s `hands[]`).
- [ ] Storage quota readout: in Settings → Storage, the
      `Browser quota` row shows `<usage> / <quota> (<pct>%)`. Quota
      should be the browser-managed origin quota; warning copy
      appears once usage > 80%.

If it fails, open the service worker DevTools (`chrome://extensions`
→ "service worker" link) and inspect the network call. The most
common cause is `FLUSH_ENDPOINT` not matching the running website
URL or its `host_permissions` allow-list.

## 5. Export `.casinodump`

- [ ] With a non-empty selection, click "Export". A `.casinodump`
      should download.
- [ ] On the website, sign in as admin, go to `/contribute`, drop
      that file on the upload form. Confirm the round shows up under
      `/data` after the page reloads.

## 6. Export readable

- [ ] With a non-empty selection, click "Export readable" in the
      extension. A `.json` file should download.
- [ ] Open it in a text editor. Confirm:
      - Top-level shape: an array of round objects.
      - Each round has `handId`, `firstTs`, `lastTs`, `hero`,
        `actions[]`.
      - `actions[]` are merged steps (postBlind, deal, bet, fold,
        showdown, etc.), NOT raw Phoenix frames.
      - For a hand whose hero name couldn't be resolved, `hero.name`
        is `null` (we don't fabricate one).

- [ ] On the website's `/data` page, select the same round and click
      "Export readable" there. Confirm the file shape matches the
      extension's output.

## 7. Delete (admin)

- [ ] Sign into the website as the admin account.
- [ ] On `/data`, select a couple of rounds. Click "Delete selected".
- [ ] Confirm those rounds disappear from the list.
- [ ] Sign out. Reload `/data`. The rounds stay gone.
      (Schema v5 dropped the soft-delete tombstone — `hand_canonical`
      rows are physically removed, and `hand_upload` children cascade
      via FK. Re-upload the original `.casinodump` if you want the
      hand back.)
- [ ] Optional: open the DB and verify the rows are absent from
      `hand_canonical` and that no orphaned `hand_upload` rows
      reference them.

## 8. Sanity sweeps on a casino-org tab

While the extension is loaded:

- [ ] Open a non-casino tab (e.g. `https://example.com`). Confirm
      DevTools → "Sources" tab does NOT show injected scripts. The
      content scripts only match `https://*.casino.org/*`.
- [ ] In casino.org DevTools, in the Console, run
      `document.cookie`. Confirm the cookie string is **not** logged
      anywhere by the extension (search the bridge log).
- [ ] Confirm the extension's storage usage in
      `chrome://extensions` → Details → "Site storage" is reasonable
      (single-digit MB for a few hands).

## 9. Off switch

- [ ] In the extension's settings card, toggle "Capture enabled" off.
      Play another hand.
- [ ] Confirm no new round shows up in Game History.
- [ ] Toggle back on. Confirm new hands resume capturing.

## 10. Uninstall

- [ ] Remove the extension via `chrome://extensions`.
- [ ] Confirm `chrome.storage.local` is gone (visit `chrome://extensions`
      → Details → Site storage; the extension is no longer listed).

---

If every box above is checked, the build is good to go. If anything
is off, the most likely culprits in order: (1) `FLUSH_ENDPOINT`
mismatch with `host_permissions`, (2) stale icon cache from an
unbumped manifest version, (3) a forgotten `npm run build` so the
zip on `/contribute` is older than the source tree.
