Skip to content

Accessibility: a blind user cannot complete wallet backup #1097

Description

@romchornyi

Summary

A blind user cannot complete wallet backup. Not "with difficulty" — the seed-phrase verification step gives no feedback a screen reader can perceive, and the only reliably announced control on that screen is Skip.

Found during the VoiceOver audit for support ticket 32072. Not addressed by #1096, which fixed the shared components, because the fix here needs a product decision first.

What is broken

The "I wrote it down" gateDashWallet/Sources/UI/Setup/SecureWallet/Seed/Views/DWCheckbox.m:137-174

A custom control that exposes no role and no checked state. VoiceOver announces nothing about whether it is ticked, and it blocks Continue (DWPreviewSeedPhraseViewController.m:150-153).

The tap-the-words-in-order verificationDashWallet/Sources/UI/Setup/SecureWallet/Seed/Views/SeedPhrase/DWSeedWordView.m:107-158

The word chips are custom UIControls with no trait, no state and no position information. A wrong word is rejected with a red flash and a shake only (DWSeedPhraseView.m:328-347) — nothing is announced, so the user gets no signal that anything happened.

Related, same flow — the seed screen auto-pops on applicationWillResignActive (DWPreviewSeedPhraseViewController.m:183-185). VoiceOver users hit interruptions more often than sighted users, so they get ejected mid-read more often.

Why it matters

The flow funnels blind users into holding funds against a seed phrase they never verified and may never have heard in full. That is a lockout risk, not a convenience issue.

The decision needed before implementing

Should VoiceOver read the recovery phrase aloud at all?

The same screen already treats the phrase as sensitive — a screenshot of it wipes the wallet. Reading twelve words aloud through a device speaker is a comparable exposure, and it is not obvious that the answer is simply "yes".

Plausible options, none of them free:

  1. Announce the words normally. Simplest, and the only option that makes the flow usable unaided — but it speaks the phrase aloud in whatever room the user is in.
  2. Announce only with headphones connected, and say why when they are not.
  3. Announce positions and state ("word 3 of 12, selected") without speaking the word itself. Preserves secrecy but makes verification unusable, since the user cannot tell which word they are picking.

This is a call for the owner / CTO, not something to settle in a PR.

Scope once decided

  • DWCheckbox — role, state, and a state-change announcement
  • DWSeedWordView — button trait, selected state, position in the sequence
  • DWSeedPhraseView — an announcement on rejection, replacing shake-only feedback
  • DWPinView.m:189-199 — PIN mismatch during setup is currently haptic + shake + a silent clear; same class of defect, same flow

Estimated 20-25 engineer-hours for the Setup zone as a whole, mostly mechanical once the policy question is answered.

Context

Note the static rules do not catch these — they are ObjC custom controls, not the icon-only-button pattern the audit rules recognise. The tooling under-reports; this was found by reading.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions