Goal
Full test coverage for every layer of the app — no "activated surface" carve-out, no untested page, no flow that can only break in production.
Status today (verified)
Verified against coverage/lcov.info (post-#539 merge, locally re-computed) and against .coverage-floor-lines = 94:
Tier / surface
Verified state
Issue
Tier 0 — cubit + service unit tests
96.89 % on activated surface (4616 / 4764 lines); floor at 94; #539 body states 96.9 % post-merge
#314 , #539
Tier 1 — multi-layer integration tests
1 spec today (kyc_sign_flow_test.dart, signer-only)
#542
Tier 2 — BitBox02 firmware simulator
hardware-connect + KYC sign + ETH personal-message already covered by testkit baselines; sell-BitBox EIP-1559 is the real gap
#548
Tier 3 — Maestro handbook
26 flows (onboarding + settings); ~25 min wall-clock today
#543
Tier 4 — BLE VCR/replay
nothing; seam currently unknown — research spike scheduled
#549
*_page.dart testWidgets specs
12 fully untested + 5 special-handling cases
#544
lib/widgets/** testWidgets specs
8 testable + 1 dead code (chain_asset_icon — delete via #560 )
#545
Bootstrap + routing
router has 0 redirect clauses; 8-branch _navigate() ladder untested
#546
Visual regression (alchemist)
PR #541 (pilot, 5 pages) + PR #552 (scale to 57 pages, 59 baselines, green CI) — both ready to merge
#547
File-pair existence guard
does not exist
#551
Full-lib coverage (excl. *.g.dart + lib/generated/**) is 86.56 % today.
Recommended execution order
After value-analysis (which bug classes are uniquely caught vs already covered by another tier), the work decomposes into three priority tiers. Total recommended scope: ~25 engineer-days (~5 weeks) — significantly less than running every issue in scope, with negligible bug-catching loss.
Tier 1 — must-do (~10.7 days)
Each item catches a bug class no other tier covers. Skip none of these.
#
Item
Days
Unique bug class
#546
Bootstrap + routing (8-branch _navigate(), DI resolution, route names)
4.0
App-boot bugs after DI refactor — nothing else catches
#547
Wrap-up + merge of #541 + #552 (already built, 57 pages, 59 baselines green)
1.0
Layout / theme drift; implicit render-crash detection
#545
Form widgets + mnemonic + image_picker_sheet
2.5
KYC input sanitization, seed-entry security, KYC document upload
#560
Delete dead chain_asset_icon widget
0.1
Quick cleanup
#551
CI file-pair existence guard
2.0
Forward-looking regression prevention
#555
Golden-update bootstrap (Option A: workflow_dispatch artifact)
0.6
Enables #547 re-bake workflow
#554
Deep-link Option A (drop dead iOS scheme)
0.5
iOS-vs-Android consistency cleanup
Tier 2 — high-value, after Tier 1 (~10.5 days)
#
Item
Days
Unique bug class
#544
Money / hardware / KYC-subpage / support / legal pages (8)
2.5
Render-crash on critical user flows
#544
Settings-tail pages with verified render logic (4)
1.5
BlocBuilder switch-arms, BlocListener side-effects, optimistic-loading timing
#544
Allow-list entries for static pages + platform-channel smoke (5)
0.5
Documentation, not testing
#542
Tier 1: sell_bitbox_flow_test + kyc_registration_flow_test only
2.0
EVM tx-sign cross-layer composition (Tier 0 mocks don't see it)
#553
Maestro auth bootstrap (Option A: debug-auth shortcut)
1.5
Enables #543 flows below
#543
KYC chain flow + 2-3 unique single-screen flows
3.0
Multi-screen routing bugs (historical PRs #332 , #466 , #523 )
Tier 3 — strategic, post-MVP (~4 days)
#
Item
Days
Note
#548
Tier 2 simulator: SellBitboxEIP1559RealUnitTx + failure-branches only
2.0
Cross-repo dep on bitbox-testkit
#557
bitbox-testkit cross-repo tracking PR
0.7
Administrative
#549
Tier 4 BLE spike (writeup only)
1.5
Output decides invest / defer / close
Skip — not recommended
Item
Days saved
Reason
#542 auth_sign_flow_test
1.0
Commit 3bee3c7 covered the auth-sign Tier-0 path; marginal value
#543 — all other 26 Maestro flows
6-7
Verified: already covered by Tier 0 + #544 + #547
#544 — settings_dfx_documents_page + settings_aktionariat_documents_page
0.5
Verified pure-static (compile-time list iteration); allow-list, don't test
#545 date_picker.dart
0.5
Cancel-semantics bug is real but consumers are non-funds-loss; allow-list with note
#548 EthAddressRealUnitMainnetExact + Sepolia
0.5
Testkit EthAddressMainnet already uses identical m/44'/60'/0'/0/0 — redundant
#554 Option B (wire deep-link handler)
2-4
Only valuable if Product wants the feature; Option A solves the inconsistency
#549 BLE implementation post-spike
2-6 weeks
Defer until spike output justifies
#556 env-flag
(closed)
Coverage-gating already solved by lcov --remove + inline coverage:ignore + Port pattern
Calendar plan
Decision-issues (each owns one prerequisite)
Coverage convention after each tier
After Tier 1 : bootstrap no longer dark; widgets that handle user input + uploads tested; file-pair guard catches new regressions; visual baselines green
After Tier 2 : testWidgets coverage exists for all rendered code; BitBox cross-layer composition tested; KYC multi-screen routing tested via chain flow
After Tier 3 : BitBox-touching ceremonies have Tier-2 firmware-simulator confidence; Tier-4 has a written invest/defer/close decision
Switch to full-lib gate : not mechanical. Real obstacles:
Definition of done
Every *_page.dart has either a *_page_test.dart, parent/combined-spec coverage, or an entry in .test-coverage-allowlist with rationale (testWidgets: spec every *_page.dart (12 untested + 5 special-handling) #544 + CI: file-pair existence guard (every page/widget needs a test or an allow-list entry) #551 )
Every lib/widgets/**/*.dart has either a *_test.dart (possibly combined), an allow-list entry, or is deleted (testWidgets: spec every shared widget under lib/widgets/ (8 testable + 1 dead code) #545 + CI: file-pair existence guard (every page/widget needs a test or an allow-list entry) #551 + chore: delete dead chain_asset_icon widget #560 )
Critical money / KYC / wallet-state BitBox flows have a Tier-1 spec (Tier 1: complete integration-test coverage for every multi-layer flow #542 )
Critical user flows + the KYC chain flow have Maestro coverage (Tier 3: extend Maestro handbook to cover every user-facing feature #543 )
BitBox EIP-1559 sell ceremony has Tier-2 firmware-simulator coverage (Tier 2: extend BitBox02 firmware simulator beyond hardware_connect_bitbox #548 )
Tier-4 BLE has a written recommendation: invest, defer, or close (Tier 4: spike — pick a test seam for BitBox02 BLE before any cassette work #549 )
lib/main.dart, router, DI, lifecycle all have direct specs (Bootstrap + routing tests: main.dart, router config, DI wiring, deep links #546 )
Visual baselines exist for every page on the dfx01 runner (Visual regression: scale from 5-screen pilot to every *_page.dart #547 + PR feat(tests): visual-regression coverage for all 57 screens on dfx01 runner #541 + PR feat(tests): scale visual regression to all 57 screens (stacked on #541) #552 )
File-pair guard prevents future regressions (CI: file-pair existence guard (every page/widget needs a test or an allow-list entry) #551 )
The 4 remaining decision-issues each have a closed decision-issue (Maestro auth bootstrap: pick a mechanism for authenticated KYC/Buy/Sell flows #553 , Deep-link wiring: drop iOS plist entries, or wire Android + Dart handler + tests #554 , Golden-update bootstrap mechanism after golden-bootstrap.yaml removal #555 , Tier 2: cross-repo tracking issue for bitbox-testkit scenarios #557 )
What gets caught (and what doesn't)
The ~25 engineer-days of recommended scope catches four high-value bug classes uniquely:
App-boot bugs after DI / routing refactor (Bootstrap + routing tests: main.dart, router config, DI wiring, deep links #546 )
EVM tx-sign composition bugs (Tier 1: complete integration-test coverage for every multi-layer flow #542 + Tier 2: extend BitBox02 firmware simulator beyond hardware_connect_bitbox #548 )
KYC input + seed-entry security bugs (testWidgets: spec every shared widget under lib/widgets/ (8 testable + 1 dead code) #545 )
Multi-screen routing bugs (Tier 3: extend Maestro handbook to cover every user-facing feature #543 chain flow)
Plus complementary coverage:
What this plan does not catch:
Closed predecessors
Goal
Full test coverage for every layer of the app — no "activated surface" carve-out, no untested page, no flow that can only break in production.
Status today (verified)
Verified against
coverage/lcov.info(post-#539 merge, locally re-computed) and against.coverage-floor-lines = 94:kyc_sign_flow_test.dart, signer-only)*_page.darttestWidgets specslib/widgets/**testWidgets specschain_asset_icon— delete via #560)_navigate()ladder untestedFull-lib coverage (excl.
*.g.dart+lib/generated/**) is 86.56 % today.Recommended execution order
After value-analysis (which bug classes are uniquely caught vs already covered by another tier), the work decomposes into three priority tiers. Total recommended scope: ~25 engineer-days (~5 weeks) — significantly less than running every issue in scope, with negligible bug-catching loss.
Tier 1 — must-do (~10.7 days)
Each item catches a bug class no other tier covers. Skip none of these.
_navigate(), DI resolution, route names)image_picker_sheetchain_asset_iconwidgetworkflow_dispatchartifact)Tier 2 — high-value, after Tier 1 (~10.5 days)
sell_bitbox_flow_test+kyc_registration_flow_testonlyTier 3 — strategic, post-MVP (~4 days)
SellBitboxEIP1559RealUnitTx+ failure-branches onlybitbox-testkitSkip — not recommended
auth_sign_flow_test3bee3c7covered the auth-sign Tier-0 path; marginal valuesettings_dfx_documents_page+settings_aktionariat_documents_pagedate_picker.dartEthAddressRealUnitMainnetExact+ SepoliaEthAddressMainnetalready uses identicalm/44'/60'/0'/0/0— redundantlcov --remove+ inlinecoverage:ignore+ Port patternCalendar plan
Decision-issues (each owns one prerequisite)
golden-bootstrap.yamlremoval #555 — Golden-update bootstrap mechanism (Option A recommended, ~0.6d)— closed as not-applicable; coverage-gating already solved/debugAuthenv feature flag — verify whether actually needed (likely close as not-applicable) #556bitbox-testkitscenarios #557 — bitbox-testkit cross-repo tracking (only relevant if Tier 2: extend BitBox02 firmware simulator beyondhardware_connect_bitbox#548 lands)Coverage convention after each tier
web_view_page.dartwrapsInAppWebViewdirectly — needscoverage:ignore-file(testWidgets: spec every*_page.dart(12 untested + 5 special-handling) #544)debug_auth_page.dartiskDebugMode-only — needscoverage:ignore-file(testWidgets: spec every*_page.dart(12 untested + 5 special-handling) #544)// coverage:ignore-*annotations before the floor can moveDefinition of done
*_page.darthas either a*_page_test.dart, parent/combined-spec coverage, or an entry in.test-coverage-allowlistwith rationale (testWidgets: spec every*_page.dart(12 untested + 5 special-handling) #544 + CI: file-pair existence guard (every page/widget needs a test or an allow-list entry) #551)lib/widgets/**/*.darthas either a*_test.dart(possibly combined), an allow-list entry, or is deleted (testWidgets: spec every shared widget underlib/widgets/(8 testable + 1 dead code) #545 + CI: file-pair existence guard (every page/widget needs a test or an allow-list entry) #551 + chore: delete deadchain_asset_iconwidget #560)hardware_connect_bitbox#548)lib/main.dart, router, DI, lifecycle all have direct specs (Bootstrap + routing tests:main.dart, router config, DI wiring, deep links #546)*_page.dart#547 + PR feat(tests): visual-regression coverage for all 57 screens on dfx01 runner #541 + PR feat(tests): scale visual regression to all 57 screens (stacked on #541) #552)golden-bootstrap.yamlremoval #555, Tier 2: cross-repo tracking issue forbitbox-testkitscenarios #557)What gets caught (and what doesn't)
The ~25 engineer-days of recommended scope catches four high-value bug classes uniquely:
main.dart, router config, DI wiring, deep links #546)hardware_connect_bitbox#548)lib/widgets/(8 testable + 1 dead code) #545)Plus complementary coverage:
*_page.dart(12 untested + 5 special-handling) #544)*_page.dart#547 — mostly already done in PR feat(tests): scale visual regression to all 57 screens (stacked on #541) #552)What this plan does not catch:
bitbox_flutter,alchemist,image_picker)Closed predecessors
/debugAuthenv feature flag — verify whether actually needed (likely close as not-applicable) #556 — env feature flag (closed: not applicable, see issue comment for verification)