---
phase: 06.6
slug: uat-accounts-integer-viewport-scaling-chat-region-clamp-righ
status: pending
last_updated: 2026-05-16
operator: decidel
---

# Phase 06.6 — Human UAT

[doc->REQ-CLI-01] [doc->REQ-CLI-02] [doc->REQ-CLI-03] [doc->REQ-CLI-05] [doc->REQ-CLI-06] [doc->REQ-CLI-08] [doc->REQ-DEP-01]

> Four small QoL verifications: UAT account capture (first-run password printout),
> integer viewport scaling at three window sizes, chat HUD clamp to canvas rect,
> right-click EscMenu trigger.

---

## Test 1 — UAT account password capture (REQ-DEP-01)

**Why manual:** The seed migration prints a freshly-generated plaintext password to stdout EXACTLY ONCE per account on first boot (R-01). The plaintext is never persisted; if the operator misses the line, the account is unrecoverable except by re-seed.

**Instructions:**
1. On first deploy of Phase 06.6 to staging, tail server logs for the seed output:
   ```
   flyctl logs -a rebno-staging | grep '\[seed-uat\]'
   ```
2. You should see two lines, each printed exactly once:
   ```
   [seed-uat] account_seeded username=dunsen_uat password=<plaintext-A>
   [seed-uat] account_seeded username=rebbie_uat password=<plaintext-B>
   ```
3. Copy BOTH plaintexts (`<plaintext-A>` and `<plaintext-B>`) into your personal password manager IMMEDIATELY — subsequent boots are silent (the existing-row branch no-ops; no re-print).
4. Open `https://staging.rebno.decidel.com/` and sign in as `dunsen_uat` with `<plaintext-A>`. Reaches GameScene successfully.
5. Sign out, sign in as `rebbie_uat` with `<plaintext-B>`. Reaches GameScene successfully.
6. Restart the staging machine (or wait for the next deploy boot) and re-tail `flyctl logs -a rebno-staging | grep '\[seed-uat\]'` — confirm NO new `account_seeded` lines appear for `dunsen_uat` or `rebbie_uat` (idempotency).

**Acceptance:**
- Both `[seed-uat]` lines captured into operator's password manager.
- Both sign-ins succeed without dev-bypass.
- No re-print on subsequent boots (idempotency verified).

---

## Test 2 — Integer viewport scaling at three window sizes (REQ-CLI-01 / REQ-CLI-06)

**Why manual:** Fractional-zoom blur on the player sprite is a perceptual call; pixel-edge crispness must be inspected by eye on real hardware.

**Instructions:**
1. Open the client at window sizes 800×600, 1280×720, and 1920×1080.
2. At each size, verify the canvas snaps to an integer zoom multiple:
   - 800×600 → zoom 1× → canvas rendered width = 640 px, height = 480 px
   - 1280×720 → zoom 1× → canvas rendered width = 640 px, height = 480 px
   - 1920×1080 → zoom 2× → canvas rendered width = 1280 px, height = 960 px
3. Open DevTools → Elements → inspect the Phaser canvas element; confirm `width` and `height` attributes (or `getBoundingClientRect()`) match the values above.
4. Confirm letterbox/pillarbox bars surrounding the canvas are `#0A0E1A` (no white/grey banding) per UI-SPEC.
5. Resize the window during play (drag corner) — the canvas re-snaps to the new integer zoom on `window.resize` without sprite blur or sub-pixel shimmer.

**Acceptance:**
- All three sizes show crisp pixel edges (no sub-integer zoom).
- Letterbox color matches `#0A0E1A`.
- Resize during play re-snaps cleanly.

---

## Test 3 — Chat HUD clamps to canvas rect (REQ-CLI-05)

**Why manual:** The chat container's geometry depends on the live Phaser canvas `getBoundingClientRect()` after rAF coalescing — a subjective placement check confirms the rect math is correct across viewport sizes.

**Instructions:**
1. Open the client at 1920×1080. The canvas centers at 1280×960 with 320 px of horizontal pillarbox on each side.
2. Open DevTools → Elements → query the chat HUD outer container; confirm:
   - `left ≈ 320px`
   - `width = 1280px`
   - `top` and `height` cover the canvas's vertical extent (no overflow above or below the canvas rect).
3. Resize the window to 1280×720 (zoom = 1×, canvas 640×480, centered with horizontal + vertical pillarbox). Chat HUD re-anchors to the new canvas rect within one frame (rAF-coalesced — D-13).
4. Walk to different positions in the room; chat input remains inside the canvas rect.
5. Confirm chat HUD NEVER paints over the `#0A0E1A` letterbox/pillarbox regions at any window size.

**Acceptance:**
- Chat container's bounding rect always lies inside the canvas's bounding rect on every tested window size.
- Resize re-anchors chat within one frame.

---

## Test 4 — Right-click opens EscMenu; left-click no-op; canvas contextmenu suppressed (REQ-CLI-02 / REQ-CLI-03)

**Why manual:** Browser context menu suppression and pointer-button discrimination depend on real OS / browser dispatch; headless Playwright cannot fully reproduce the right-click + native contextmenu interaction.

**Instructions:**
1. In GameScene, **left-click** on the canvas — confirm NOTHING happens: no EscMenu opens, no browser context menu appears.
2. **Right-click** on the canvas — EscMenu opens (R-04 / D-14).
3. Confirm the browser's default `contextmenu` does NOT appear on the canvas (Phaser `this.input.mouse?.disableContextMenu()` is canvas-scoped per R-04 — supersedes D-15 hand-rolled document listener).
4. Right-click inside the chat input element — the browser's default `contextmenu` DOES appear (copy/paste/select-all preserved because `disableContextMenu` is canvas-scoped, not document-scoped).
5. Press **ESC** — EscMenu toggles via keydown path (unchanged by Phase 06.6; D-34 guards preserved).
6. Log out, sign back in, return to GameScene, right-click on canvas again — context menu still suppressed (Pitfall 6 — `disableContextMenu` re-installs on every `GameScene.create()`).

**Acceptance:**
- Left-click on canvas is silent (no menu, no contextmenu).
- Right-click on canvas opens EscMenu and suppresses browser contextmenu.
- Right-click on chat input still opens browser contextmenu (canvas-scope preserved).
- ESC keydown still toggles EscMenu.
- Logout + login round-trip: contextmenu still suppressed on canvas.

---

## Operator parallel-UAT scenario

The new real-account login (`dunsen_uat` / `rebbie_uat` via captured plaintext from Test 1) is **collision-free** with the existing dev-bypass UAT (`?dev-bypass=uat_a` / `?dev-bypass=uat_b` synthetic tokens) per R-02. The dev-bypass tokens never write to the `user` or `account` tables — they short-circuit auth via in-memory session shims (see Phase 06.5 UAT model). The two paths can run concurrently in separate browser windows without crosstalk.

**Recommended parallel scenario:**
1. Browser window A: sign in as `dunsen_uat` with the captured plaintext password (Test 1 path — exercises the real Better-Auth flow).
2. Browser window B (separate profile or incognito): open `https://staging.rebno.decidel.com/?dev-bypass=uat_a` (existing dev-bypass path — exercises the synthetic session shim).
3. Confirm both characters appear in the same room; both can move and chat without crosstalk.
4. Verify the dev-bypass session in window B never persists a row in the `user` or `account` tables (no entry for synthetic username `uat_a` after the session ends — DB inspection via staging shell or the existing `account` table query).

This dual-UAT mode is the operator's primary workflow for Phase 06.6+ regression: real accounts validate the auth surface; dev-bypass:uat_a accelerates per-feature smoke without re-typing passwords.

---

## Sign-Off

| Test | Requirement | Status |
|------|-------------|--------|
| 1 — UAT account password capture | REQ-DEP-01 / REQ-CLI-03 | ⬜ pending |
| 2 — Integer viewport scaling | REQ-CLI-01 / REQ-CLI-06 | ⬜ pending |
| 3 — Chat HUD clamps to canvas rect | REQ-CLI-05 | ⬜ pending |
| 4 — Right-click EscMenu + contextmenu scoping | REQ-CLI-02 / REQ-CLI-03 | ⬜ pending |
| Operator parallel-UAT scenario | REQ-CLI-08 | ⬜ pending |

**Operator approval:** ⬜ pending — sign with date + outcome once staging deploy of Phase 06.6 is complete and tests 1–4 have been exercised.
