You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
Copy file name to clipboardExpand all lines: docs/DEPLOYMENT_PLAN.md
+37Lines changed: 37 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,6 +33,43 @@ The deploy script absorbed each of these as it learned. End state: cache-warm re
33
33
-**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.
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).
**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).
- 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.
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