Skip to content

feat(maestro): add KYC link-wallet BitBox-connect E2E flows#732

Open
TaprootFreak wants to merge 8 commits into
stagingfrom
feature/maestro-kyc-link-wallet-v2
Open

feat(maestro): add KYC link-wallet BitBox-connect E2E flows#732
TaprootFreak wants to merge 8 commits into
stagingfrom
feature/maestro-kyc-link-wallet-v2

Conversation

@TaprootFreak

Copy link
Copy Markdown
Contributor

Summary

Changes

#553 — Maestro Auth Bootstrap

  • MaestroMockClient intercepts DFX API calls, returns canned responses
  • MaestroRegistrationService simulates BitboxNotConnectedException on first call
  • Wired via --dart-define=MAESTRO_MOCK=true, zero impact on production

#727 — KYC link-wallet flow

  • Two handbook flows (11a, 11b): KYC navigation + BitBox connect sheet regression guard
  • CI builds tier3 with --dart-define=MAESTRO_MOCK=true

Review findings addressed

  • Fixed back-navigation gate logic in flow 11b
  • Fixed import ordering, mock response completeness, flow counts
  • Added tests: MaestroMockClient (10) + MaestroRegistrationService (1)

🤖 Generated with Claude Code

Add Maestro handbook flows for the KYC "add wallet" path with a
regression guard for the BitBox-connect sheet (PR #720). Introduces
an in-process HTTP mock layer (`MAESTRO_MOCK`) that enables
authenticated KYC flows without a real backend.

- MaestroMockClient: intercepts DFX API calls under MAESTRO_MOCK
- MaestroRegistrationService: throws BitboxNotConnectedException on
  first registerWallet() call to exercise the connect-sheet path
- Two new handbook flows (11a/11b): navigate KYC → legal disclaimer
  → link-wallet page → tap submit → BitBox connect sheet → dismiss
- CI build tier3-handbook with --dart-define=MAESTRO_MOCK=true
- BuyView redirects to /kyc in mock mode for deterministic entry
- Fix flow 11b back-navigation: single retry-gated loop instead of
  two separate blocks with incorrect gate condition
- Fix import ordering in di.dart (maestro_* before real_unit_*)
- Fix _continueKycResponse: add missing kycLevel, kycSteps, status,
  sequenceNumber, isCurrent, and session.type fields
- Update all flow-count references from 26 to 28 in run-handbook-flows.sh
- Add unit tests for MaestroMockClient (10 tests) and
  MaestroRegistrationService (1 test)
- Merge PR #720 (BitBox connect sheet in link-wallet step)
@TaprootFreak TaprootFreak added the tier3:full Opt-in: run Tier 3 Maestro handbook flows on this PR label Jun 10, 2026
@TaprootFreak TaprootFreak marked this pull request as ready for review June 10, 2026 13:21
…paths to real API

The previous approach set _localTesting=true under MAESTRO_MOCK, which
routed ALL API calls to localhost:3000. The mock's fallback empty-{}
response for unknown paths crashed dashboard services that expect List
responses (TransactionHistoryService, DFXPriceService, etc.), causing
red error overlays during flows 01-26.

Fix:
- Revert _localTesting to always false (apiHost stays api.dfx.swiss)
- Remove /v1/auth mock intercept — let the app get a real auth token
- Forward unknown paths to a real HTTP Client so dashboard/price/
  balance calls hit api.dfx.swiss with valid credentials
- Only KYC/registration paths are intercepted by the mock

Also remove misleading handbook screenshot mapping comment from flow
11a (no mapping exists in assemble-handbook-screenshots.sh).
- Remove unused MockSessionCache class and dead imports from
  maestro_registration_service_test.dart
- Fix outdated tier3-handbook.yaml build-step comment that described
  the old _localTesting=true / empty-200 fallback approach
- Rename local helper functions to drop leading underscore
- Add const to RealUnitUserDataDto constructor
The KYC flow calls getAuthToken() which hits POST /v1/auth when no cached
token exists. Onboarding flows (01-10) never call getAuthToken() — the
token is null when flow 11a enters the KYC path, so getAuthResponse()
falls through to the real DFX API. On GitHub Actions runners whose IP is
geo-blocked, the real API returns 403 ("The country of IP address is not
allowed"), which surfaces as a KycFailurePage instead of the expected
legal disclaimer.

Return a synthetic accessToken from the mock so authenticatedGet
succeeds without any real-API round-trip.
The legal disclaimer page uses "Zustimmen" / "Ablehnen" (localized via
legalDisclaimerYes/No), not "Ja" / "Nein". The flow's repeat block was
tapping a non-existent element.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tier3:full Opt-in: run Tier 3 Maestro handbook flows on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant