Katomia board — QA test dimensions & cases

First cut 2026-07-15 (user request, tablet session KY564). Purpose: a shared checklist for manual passes now, and the enumeration an automated end-to-end suite grows from later — WalletConnect flows can be automated headlessly via the XPROOF project's headless-WC facility (Playwright). AUTO = automatable today, MANUAL = needs eyes (animation/visual judgement).

1 · Test dimensions (the combination axes)

DimensionValuesNotes
Device / inputdesktop (mouse), tablet (touch), phone (touch, small)touch-drag vs mouse-drag vs tap-to-offer paths differ; known device-dependent snags live here
BrowserChrome, Edge, Firefox, Android WebView/Samsung Internet, iOS Safarithumb-render inconsistencies already logged in BOARD-POLISH1 (3)(4)(6)
Networkplaynet, testnet, mainnetplaynet: no WC, manual labels only; mainnet: real-value guard rails
Trading modeproposal (board), orderBook, debugboard = proposal only today
Chip layout 🧪shelves, organicboth live until the desktop verdict (BOARD-LAYOUT1)
Net view 🧪on (standard), offoff is the escape hatch; withdraw-all only applies when on
Account sourceWalletConnect (HashPack et al), manual entry, mixedprofile WC list vs game accounts are separate stores (KAT-ACCTNORM1)
Accounts per player1, 2, many (> max-on-ring)wheel windowing + divider wedges engage past the cap
Playerssolo (2 own accounts), 2 players, many (> max-on-ring)party-only + cluster semantics need ≥3
Asset kindHBAR, FT (decimals known/unknown), NFT, mixed basketsunknown-decimals guard = AMOUNT-SCALE1 incident
Association stateassociated, not associated + auto-assoc slots (unlimited / limited / full)warning-cue logic under review (SIGN-ASSETASSOC1)
Lock ruleall, active, clusterparty-only filter follows it
Board motionyou-at-bottom toggle, party-only toggle, wheel scroll, max-on-ring change, resize/orientationeach must clear stale trail lines; chips must not jump (glide)
Settingseach ⚙ control × persistence (reload) × live effectskin, net, self-bottom, max-on-ring, anim speed, trail after-glow, chip layout, party-only, pickable
Signing outcomesuccess, failure, EXPIRY (no receipt ever), partial sigs, witness sigexpiry verdict signal-driven (backend resolve broadcast); square 🟩/🟥 banner
Connection healthstable, WS drop/reconnect, slow mirror, mid-flow refreshadd-account late-land (30s+60s poll) lives here

2 · Core flow cases

#CaseExpected
F1Add account — WC connect, fresh pairing, join allcomposer jumps re-pick step; account lands ≤30s or late-land toast; footer selects itAUTO
F2Add account — manual entry, selected assets subsetbracket-notation join; only ticked assets arriveAUTO
F3Add account — EMPTY footer list➕ button (not dead select) opens composerAUTO
F4Offer fungible slice (drag AND tap-to-offer)amount prompt; chip flies pile→basket dropping ghost at rim; 3-point line; store balance decrementsMANUAL
F5Offer NFT (drag AND tap-to-offer)arc flight store→rim (ghost dropped)→straight→basket; no kinked linesMANUAL
F6Withdraw netted stack (net on)confirm names FULL amount; all legs return; after-glow lines cleared; chips glide homeAUTO
F7Reject received offerchip animates back to giver; same clearing as F6AUTO
F8Lock / unlock via arc tap + footerarc thickens orange; hover preview dashed; all-locked → signing phaseMANUAL
F9Sign — party account (WC prompt → approve)green status arc; sign saved; banner "signing mode" visibleAUTO
F10Sign — NON-party accountbutton still ✍ Sign (witness tooltip), never Lock, no errorAUTO
F11Transaction successconfetti burst from hub (canvas-confetti), 🟩 banner + alert, board resetsMANUAL
F12Transaction EXPIRY (let countdown lapse, sign nothing)~11-16s after countdown: wiper sweep + persistent 🟥 toast (closable, never auto-dismisses) — never silenceAUTO
F13▶ preview replayflights ghost→basket + pile→ghost trail segments; spotlight fat-tire + blurred edge; ghosts inside the lightMANUAL

3 · Layout / geometry cases

#CaseExpected
L1Rim band reservedstore chips never enter the ghost band; ghosts alone at the counter (both layouts)AUTO
L2Coin-label bandno chip overlaps the curved account number (34px basket inset)MANUAL
L3Ghost colinearitypile→ghost→basket on one straight line; hover lights all threeAUTO
L4Dense store (10+ mixed chips)shelves: tidy rows, spill outward only; organic: no neighbour-wedge invasionMANUAL
L5Narrow wedge (many players)chips wider than the chord centred, no neighbour overlapMANUAL
L6Layout toggle shelves↔organicevery chip FLIP-glides; no stale cache arrangement; trails clearedMANUAL
L7Every board motion (dim: Board motion)trail lines removed at motion start; chips settle without jumpMANUAL
L8Mobile scroll attemptboard does not drag/bounce (dvh + overscroll fix); hub stays centredMANUAL

4 · Transaction timing & validity (KATOMIA-VALIDDUR1)

One number crosses five components and produced three distinct silent-fallback bugs in one day (2026-07-15) — each decode path falls back to a plausible default (120s, the SDK default) instead of failing loud, so wrong values are invisible unless a NON-default duration is configured. Rule of thumb for all timing tests: always test with a duration ≠ 120 and ≠ 40 (the two defaults in play) and within Hedera's legal 15–180s — below 15s the NODE precheck-rejects submission with INVALID_TRANSACTION_DURATION (found live 2026-07-15: a 5s game silently killed every SIGNED tx while unsigned ones expired normally, masking it); all layers now clamp, e.g. use 16s — then every fallback is visible as a wrong number.

ConceptDefinitionOwner
validStarttx timestamp (after the @ in the txid); consensus nodes reject txs submitted before it. Set = now + config.txDelaySecondsbackend postCluster
validDurationwindow from validStart within which a consensus node will still accept the tx on submission (nothing is on-chain before submission). SDK default 120s; game default 40sdeal.js setTransactionValidDuration, from config.validDurationSeconds
graceTX_GRACE_MS (10s, was 30s until 2026-07-15) detection slack the backend worker adds before failing — NOT part of the validity windowkatomiaWorker
resolutionworker check cadence 5s; board clears on the backend's resolve broadcast (signal-driven, no client clock)katomiaWorker → broadcast → board

Expected end-to-end timeline for duration D with no signatures: countdown shows D from validStart → hits 0 at validStart+D → backend fails it by validStart+D+10s(+≤5s poll) → board wiper + 🟥 within ~2s of that broadcast. Anything else = a specific component below.

#TestPins
U1-U12node qa-validdur-tests.js (backend repo root) — decode matrix: Long int64 (bug #1), SignedTransaction wrapper (bug #2), cross-shape misuse silent-fallback modes, absent field, garbage, REAL production fixture bytes, expiry arithmetickpoolHelpers decoders + worker expiry contractAUTO ✅
T1create game duration=15 → inspect create-request elog + strike-window elogform → API → game.config → postCluster (the 15-became-40 leg)AUTO
T2strike → txRead detail=1 → decode bodyBytesHex → assert 15postCluster → deal.js → signed bytesAUTO
T3strike → worker "expiry set" elog: usedDurationS=15, source=recordworker input priority (record → bytes → default)AUTO
T4let it lapse → resolveTxFailed broadcast by validStart+15+10(+5)worker deadline arithmetic + cadenceAUTO
T5board: kdiag board:signing:window shows durationSource=broadcast, expiry=validStart+15s from the FIRST event (no fallback-guess flash)getTxPublicRecord broadcast → boardDetectSigning priorityMANUAL→AUTO
T6board: wiper + 🟥 verdict within ~2s of tx vanishing from pending; banner staged ⏳→✍ across validStart when txDelaySeconds > 0signal-driven verdict + banner stagesMANUAL
T7pre-deploy tx (no broadcast field): countdown upgrades fallback→bytes-decode when the signstatus poll lands (visible in board:signing:window)source-priority fallback chainMANUAL

T1–T4 are backend-only (curl + log grep — no browser, no WC): natural katrun scenario when automated (KATRUN-KFLOW1 pattern; kflowSpec.js already defines the test:start→test:verdict unit shape). T5–T7 need the board; kdiag events (board:signing:window, board:signstatus.validDurationSeconds, backend KATOMIA-VALIDDUR1 elogs) are the assertion surface for kflow units per KFLOW1.

5 · Known device-dependent watch list

ItemWhere seenStatus
Offer animation missing on own drops (touch)Samsung S6 tablet, KY564 1/300fix shipped 2026-07-15 (own-move skip removed) — retest
NFT under coin labelsame sessionband fix shipped — retest
Thumbs render as text on some browsersEdge/Firefox/mobile (BOARD-POLISH1)open, enrichment/thumb-cache family
Auto-association dotted-red false alarmHashPack auto-assoc accountsadvice pending (SIGN-ASSETASSOC1) — cue should check free slots

Maintenance: add a row when a bug is found or a feature lands; promote MANUAL→AUTO as the headless-WC suite grows. Served at /m/katomia/kontext/qa-test-dimensions.html.