Skip to content

Commit 7dc5d96

Browse files
docs(plan): record Pre-Mainnet 5.2 dealer code-complete + review #19
Update both top-level plan files to reflect the dealer productionization work landed in commits 801e230 + 3601ee8 + the auto-commit tick refactor + test coverage. EXECUTION_PLAN.md: - Header: 2026-04-28 status now mentions "Pre-Mainnet 5.2 / Phase 4 dealer service CODE-COMPLETE pre-deploy", reviews through #19. - New top-of-status entry covering the five locked-in decisions (dedicated dealer keypair / polling auto-commit with 5s tick / commit_deck submission extracted / frontend hit() wired / nginx /api/dealer route), the heavy-duty review #19 findings (1 Critical / 3 High / 3 Medium, all fixed pre-commit) with concrete remediations per finding, and the operator-action gating list for the actual deploy. - "All workspaces green" line: re-verified 2026-04-28; test counts updated (clients/js 35 -> 81 from 5.0.10, dealer now 27 with regression coverage gap closed for H1/H2). - "What's next" rewritten so the dealer deploy + the test coverage are the top items. DEPLOYMENT_PLAN.md: - New "Pre-Mainnet 5.2 / Phase 4 (dealer service)" subsection inserted before the 5.0.10 entry. Decision summary, review #19 fixes table, deploy-step checklist (keypair generation, fund + transfer, fresh game init, scp keypair, prod env file, quadlet, nginx diff, deploy-tucker.sh integration, smoke curl, demo-banner removal). Notes the live game_id=2 keeps its current dealer field (= CLI wallet) because `set_dealer` isn't exposed on chain - production needs a fresh game id. - Acknowledged known gap (no automated dealer tests at the time of writing) - closed in this same PR by the auto-commit.test.ts file.
1 parent 62e61eb commit 7dc5d96

2 files changed

Lines changed: 69 additions & 6 deletions

File tree

docs/DEPLOYMENT_PLAN.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,43 @@ The deploy script absorbed each of these as it learned. End state: cache-warm re
3333
- **Stray `pushflip-faucetatest:latest` typo'd image tag** reappeared on tucker after a `podman rmi` cleanup — likely regenerated from build history. Cosmetic; investigate next deploy if it persists.
3434
- See **Phase 5.5 deferred list** (further down) for Helius Developer-tier upgrade trigger, dealer productionization, Cloudflare orange-cloud re-enable, monthly podman prune cron, keypair rotation SOP, GitHub Actions CI, Prometheus monitoring.
3535

36+
### Pre-Mainnet 5.2 / Phase 4 (dealer service) — CODE-COMPLETE pre-deploy 2026-04-28
37+
38+
The ZK dealer that previously ran only inside `scripts/smoke-test.ts` is now a long-running Hono daemon at [`dealer/src/service.ts`](../dealer/src/service.ts) wrapping the existing `Dealer` class. Five decisions locked in (full rationale in [`docs/wiki/operations/dealer-runbook.md`](wiki/operations/dealer-runbook.md)):
39+
40+
1. **Dedicated dealer keypair** (Option C) — `init-game.ts` accepts `DEALER_PUBKEY` env var; the production game gets initialized with a separate `pushflip-dealer.json` keypair so tucker compromise yields "can re-shuffle this game's deck", not arbitrary token movement. Same blast-radius separation as the 5.0.7 faucet keypair pattern.
41+
2. **Polling auto-commit**`startAutoCommitLoop` polls GameSession every 5s, triggers `commit_deck` when `!round_active && !deck_committed && active_player_count >= 2 && round_number !== committedRoundNumber`. `commitInFlight` mutex claimed BEFORE the first await (H2 race fix). Reset gated on `!roundActive && !deckCommitted` so the loop doesn't wipe the local Merkle tree between commit and start_round (H1 state-machine fix).
42+
3. **`commit_deck` submission** extracted to [`dealer/src/commit-tx.ts`](../dealer/src/commit-tx.ts) — single shared helper between auto-loop and any future caller. `COMMIT_DECK_COMPUTE_LIMIT=400_000` lives next to it.
43+
4. **Frontend `useGameActions.hit()` wired** — reads on-chain `roundNumber + drawCounter`, fetches reveal from `GET /api/dealer/reveal/:gameId/:roundNumber/:leafIndex` (5s timeout, schema-validated, hex-decoded Merkle proof), then submits the hit ix.
44+
5. **nginx route `/api/dealer/*``127.0.0.1:3002`** — full diff against the live `play.pushflip.xyz.conf` inlined in the runbook. Separate rate-limit zone (`dealer_req`, 20r/s burst 30). Dealer service binds explicitly to `127.0.0.1` so nginx is the only ingress despite `Network=host`.
45+
46+
**Heavy-duty review #19 clean** (1 Critical / 3 High / 3 Medium, all fixed pre-commit):
47+
- C1: `dealer/Dockerfile` workspace-rewrite list now includes `dealer/package.json` (was missing — Lesson #55 redux).
48+
- H1: deck-committed-vs-round-ended distinction in the auto-loop reset branch.
49+
- H2: mutex claimed before first await (no parallel commits across racing ticks).
50+
- H3: unauthenticated `POST /commit/:gameId` operator-override deleted.
51+
- M1: explicit `127.0.0.1` binding (was inheriting `0.0.0.0` from `@hono/node-server`).
52+
- M2: hex regex no longer case-insensitive.
53+
- M3: Dockerfile comment env var corrected (`DEALER_ZK_ARTIFACTS_DIR``ZK_ARTIFACTS_DIR`).
54+
55+
Commit chain: `801e230 feat(dealer): productionize ZK dealer as long-running HTTP service` + `3601ee8 docs(dealer): document Pre-Mainnet 5.2 locked-in decisions + nginx diff`.
56+
57+
**What's required to actually deploy** (gated on operator action; runbook step-by-step in `docs/wiki/operations/dealer-runbook.md`):
58+
- Generate the dealer keypair: `solana-keygen new --outfile ~/.config/solana/pushflip-dealer.json`
59+
- Fund it: `solana transfer <pubkey> 0.5 --url devnet`
60+
- Init a NEW game with `DEALER_PUBKEY=<pubkey> pnpm --filter @pushflip/scripts init-game` — the live `game_id=2` keeps its current dealer (= CLI wallet); production needs a fresh game id since `set_dealer` isn't exposed on chain.
61+
- `scp` the keypair to tucker (mode 0600 both ends).
62+
- Create `dealer/.env.production` on tucker (PORT=3002, ALLOWED_ORIGINS, RPC/WS, DEALER_KEYPAIR_PATH, ZK_ARTIFACTS_DIR=/app/zk-artifacts, GAME_ID).
63+
- Add `~/.config/containers/systemd/pushflip-dealer.container` quadlet (template in runbook).
64+
- Apply the nginx diff in `~/repos/server-config/nginx/conf.d/play.pushflip.xyz.conf` + reload nginx.
65+
- Fold the dealer build into `scripts/deploy-tucker.sh` (`SERVICES` + `CONTAINER_IMAGES` arrays + a third `podman build --network=host -t localhost/pushflip-dealer:latest -f dealer/Dockerfile .` step).
66+
- `bash scripts/deploy-tucker.sh`. Smoke: `curl https://play.pushflip.xyz/api/dealer/health`.
67+
- After it's live: delete `<DemoStageBanner>` and its mount in `app.tsx`.
68+
69+
**Known gap**: dealer service has no automated tests of the auto-commit state machine. The H1/H2/H3 findings were state-machine bugs that targeted unit tests would have caught. Tracked as the next follow-up work item.
70+
71+
---
72+
3673
### Pre-Mainnet 5.0.10 (display names) — DEPLOYED 2026-04-28
3774

3875
Live in production. Adjective-noun nicknames (`woodland-quasar`, `fond-turquoise`, `fresh-galaxy`, …) replace `UoZh…naxa`-style truncations across the wallet pill, player rows, turn indicator, and event feed. localStorage persistence (5.0.10.b) means hard-refreshes don't burn a registry round-trip on previously-seen addresses.

0 commit comments

Comments
 (0)