A user who created a wallet in AutistMask and did not write the phrase
down had no way to retrieve it. Adds a "Show recovery phrase" action on
the wallet row in Settings, next to the per-wallet actions that already
live there, mirroring the per-address private key export in structure,
password gate and warning treatment.
The screen displays the secret that owns every address in the wallet, so:
- Only HD wallets are offered it. walletHasRecoveryPhrase() is an
allowlist on type "hd", so the key and xprv types — which have no
phrase at all — are excluded, as is any type added later.
- Nothing is decrypted and nothing enters the page until
decryptWithPassword accepts the password. A wrong password produces a
full-sentence error and leaves the value node empty.
- Leaving the screen wipes it by any route, not just "Back": views that
hold a secret register a cleanup with showView() via onViewLeave(),
which also covers the settings gear.
- A decrypt still in flight when the screen is left is discarded rather
than written. reveal() captures a generation counter that every
clear() bumps and refuses to touch the DOM if it has moved: without
that check the write lands after the wipe, and nothing is scheduled to
wipe again, so the phrase stays in the hidden screen for the life of
the popup. crypto_pwhash is synchronous, so the reachable window is a
still-pending sodium.ready on the first vault use of a page load.
- The phrase is never assigned to state, so it cannot be persisted, and
the view is not in RESTORABLE_VIEWS — reopening the popup lands on
Home. That set moves to src/popup/restorableViews.js so the exclusion
can be asserted directly; the popup entry point cannot be required
outside a browser.
- The phrase cannot reach the logger: the view does not import
src/shared/log.js, and the failed-decrypt path reports a fixed
sentence rather than the caught error.
show() also pushes the navigation stack itself, because it can return
without navigating when the wallet has no phrase; pushing in the Settings
click handler left an entry no screen transition matched.
Tests: unit coverage for the type gate, the RESTORABLE_VIEWS exclusion
and the absence of any logger path; the DOM behaviour is driven against
the real popup in the e2e suite, which is where this repo tests views —
including a probe that leaves the screen while the decrypt is in flight
by dispatching both clicks in one page task, since a human cannot
interleave them once libsodium's wasm is warm.
7.8 KiB
Workflow
git pullnextand cut a branch from it — one branch per issue, namedissue-<N>-<slug>. Never branch frommain.- Do the work as one commit whose title ends with
(closes #N), with theTODO.mdupdate in that same commit. - Move Next Step to the top of Completed Steps; move the top item of Future Steps into Next Step.
- Run
make fmt, thenmake check. A feature branch may be red;nextandmainmay not. - Rebase onto current
nextimmediately before pushing — other branches land onnextcontinuously — and re-runmake checkafter resolving, because a clean textual merge can still break the build. - Push the branch and open one PR per issue with base
next. Never basemain. - An independent reviewer who did not write the change gates the merge. On a
passed review the PR is squash-merged into
next. nextis the branch for the next milestone. It is kept green and mergeable tomainat any moment, without notice.mainreceives exactly one PR per milestone, fromnext. Releases are tagged frommain.
Status
pre-1.0, working towards the 1.0.0 milestone. Tagged v0.1.0 on 2026-02-27. The
milestone is in flight on next; its next -> main PR is
#190. make check verified
green on next at e9fa8be on 2026-08-10, and make build produces
dist/chrome/ and dist/firefox/ with every bundle verified to have DEBUG
compiled off.
The backlog lives on the
Gitea tracker, which is
authoritative; this file does not duplicate it. Full policy file set present. A
real-browser end-to-end suite (make test-e2e) now sits alongside make check,
which cannot see a runtime ReferenceError in a popup view.
Next Step
Land #152: add ESLint to
script/lint. make check is prettier --check only today and cannot catch
undefined identifiers, which is how
#150 and
#151 shipped.
Completed Steps
- 2026-08-11: Password-gated recovery phrase display for HD wallets, reached from the wallet row in Settings, wiped on leaving the screen and excluded from the views the popup can reopen onto (#161).
- 2026-08-11: Policy compliance sweep — conditional verbose test rerun, local
Tailwind binary instead of
npx,--frozen-lockfileonmake install, and the Makefile-only targets documented in the README (#166). - 2026-08-11:
script/verify-builddiagnostics corrected: the both-markers message now states what is and is not proven, an unreadable bundle is diagnosed as an I/O fault rather than as changed output, the*.jsassumption lives only inbuild.js, and the unlisted-bundle scan hard-fails when it cannot enumeratedist/(#180). - 2026-08-11: Three
README.mdclaims corrected against the code — blocklist attribution, token-display rule, navigation model (#213). - 2026-08-11: README Screen Map rebuilt from the code — every screen, element
and transition re-verified against
src/popup/(#164). - 2026-08-11:
docs/README.mdrewritten against the code: no competitor names, all five network destinations documented, password/Settings/Add Wallet sections corrected (#163). - 2026-08-11:
loadState()now deriveshasWalletfrom the wallet list instead of trusting the persisted flag, so a profile already saved inconsistent no longer stays broken on every load (#195). - 2026-08-11: Wallet deletion repairs its own state —
hasWalletfollows the remaining wallets, the selection only moves when it was deleted, and the active-address change is broadcast to connected sites (#156). - 2026-08-11: One row per on-chain value movement in transaction history: the
merge moved into the pure
mergeTransactionsand the zero-ETH native side of a plain ERC-20 transfer absorbed into its token row (#177). - 2026-08-11:
TODO.mdWorkflow rewritten to the branch-and-PR-per-issue model onnext, with Status and Next Step refreshed (#191). - 2026-08-09:
DEBUGbecame a build-time constant defaulting to off, injected as the__BUILD_DEBUG__esbuild define and turned on withAUTISTMASK_DEBUG=1, so a plainmake buildno longer hands every newly created wallet the publicly committed test recovery phrase (#149). - 2026-08-09: dApp approval signing moved into the popup — the password no longer crosses the extension messaging boundary; the background broadcasts and resolves approvals only, and verifies the signed artifact against the approval it holds (#157).
- 2026-08-09: Post-build assertion that every emitted bundle containing
constants.jshasDEBUGcompiled off, viascript/verify-buildon themake buildpath (#170). - 2026-08-09: Containerized Chrome end-to-end harness (
make test-e2e/script/test-e2e) driving the real popup with all network intercepted, plus the two used-but-not-imported crashes it caught: AddToken unreachable (#150) and TransactionDetail broken for every ERC-20 transfer (#151). Harness demonstrated failing before the fixes and passing after (#181). Interception covers the MV3 background service worker, not just the popup page, and a launch-time canary aborts the suite if worker traffic starts escaping. - 2026-08-09: Reviewed the repo end to end and filed the 1.0.0 backlog (#149-#168).
- 2026-08-09: Test coverage for the address-poisoning defense in
src/shared/transactions.js(#160) - 2026-07-26: About well in settings with build info, repo link and the version click easter egg (#145); proper view navigation stack (#146).
- 2026-07-07 Adopted scripts-to-rule-them-all:
script/entrypoints, Makefile shims, README Entrypoints section (#148) - 2026-03-01: USD display suppressed on testnets (#142); estimated USD for ETH in approve-tx view (#141).
- Sepolia testnet support (#137); etherscan links go to token-specific URLs (#136).
- Transaction detail improvements: Type field and on-chain details (#130), txid-first reordering (#133), swap display corrections (#128), expanded confirm-tx warnings (#118).
- Dark mode theme setting (Light/Dark/System) with contrast fixes (#126); timestamps include timezone offset (#120); layout shift audit, reserved space for error messages (#124).
- Copy-flash visual feedback with timing tune (#113, #121); cross-wallet-type duplicate detection (#115).
- 2026-02-27: v0.1.0 tagged.
- 2026-02-24: Initial scaffolding: popup UI, BIP-39 wallet creation via ethers.js, wallet persistence, real ETH balances over RPC, ENS forward and reverse resolution.
Future Steps
Only work that has no issue of its own belongs here; everything else is on the tracker.
- Pre-1.0 security review of the extension (key handling, DEBUG mode policy, RPC input validation) before any 1.0rc tag. Individual filed issues are parts of it, but the review is broader than any of them.
- Decide whether docker-in-docker makes
make test-e2erunnable in the Gitea workflow. Extending the suite itself is tracked as #183 and #184. - Cut 1.0.0 once the milestone is empty, then continue tagging as milestones land.