# TrackCode: format & randomness ✔ 12 chars = 9 letters + 3 digits, digits only in the middle (30k samples) ✔ no duplicates in 30k samples ✔ digit positions are random (each of positions 1..10 used, 0 and 11 never) # TrackCode: normalize / issue / find ✔ normalize lowercase+spaces+dashes ✔ normalize persian digits ✔ rejects wrong length ✔ rejects wrong digit count ✔ issue returns valid code ✔ issue is idempotent per (kind, ref) ✔ same ref other kind → different code ✔ unknown kind refused ✔ find works case-insensitively ✔ find unknown → null ✔ 300 issued codes all unique ✔ line() renders code # CardConfig ✔ default (no row) = enabled with constants ✔ validNumber accepts persian digits/spaces ✔ validNumber rejects bad ✔ saved values are read back ✔ delete: disabled, number gone, defaults NOT used again ✔ mask hides middle # TrackAdmin lookup ✔ deposit: shows type, user, amount, status ✔ deposit: approve/reject + control + refresh buttons ✔ deposit approved: no action buttons, shows confirmed ✔ crypto deposit: coin/network/hash + crypto buttons ✔ withdrawal engine issues a code automatically ✔ withdrawal: amount, destination, pending + approve/reject ✔ withdrawal pending: no ledger yet (funds only reserved) ✔ withdrawal paid: status + ledger entry + no action buttons ✔ subscription: product, toman, hash, receipt btn, approve btns ✔ receipt button forwards stored photo ✔ kyc: fee, method, pending + approve/reject + receipt ✔ kyc receipt forwarded ✔ kyc: stale code flagged, no approve buttons ✔ bonus request: mode/credit + review button ✔ invalid format message ✔ unknown code message ✔ ask sets state ✔ onText resets state and shows result ✔ isKnownCode true/false ✔ lookups are audited ✔ route ignores foreign callbacks # CardAdmin ✔ non-senior sees masked number and no edit buttons ✔ senior sees full number + all actions ✔ non-senior cannot delete ✔ set: asks number ✔ set: invalid number rejected, still waiting ✔ set: number accepted → asks owner ✔ set: owner → asks bank ✔ set: saved (bank kept via "-") ✔ set: other admin notified + audited ✔ edit owner only ✔ edit bank only ✔ toggle withdraw-to-card off ✔ toggle withdraw-to-card on ✔ delete asks confirmation (nothing deleted yet) ✔ delete: card fully removed everywhere ✔ delete does NOT close withdraw-to-card (stays ON) ✔ delete: audited (masked) + others notified ✔ after delete: panel says removed, offers register-new, no number shown ✔ stored JSON contains no card digits after delete ✔ re-register after delete re-enables the deposit card ✔ withdraw-card manually OFF ✔ delete keeps withdraw-card OFF (preserves admin choice) ✔ re-register keeps withdraw-card OFF ✔ panel says withdraw-card OFF independently ✔ onText ignores foreign steps # Latin owner/bank for non-Persian users (v2.9.4) ✔ fa user sees Persian owner ✔ de user sees Latin owner (dictionary) ✔ ru user sees Latin bank (dictionary) ✔ admin-supplied Latin wins ✔ unknown value falls back to original (never a wrong name) result: 72 passed, 0 failed