Skip to content

Route post-merge NewRegistration to the registration form instead of register/wallet#711

Closed
TaprootFreak wants to merge 1 commit into
stagingfrom
fix/realunit-merge-new-registration-handoff
Closed

Route post-merge NewRegistration to the registration form instead of register/wallet#711
TaprootFreak wants to merge 1 commit into
stagingfrom
fix/realunit-merge-new-registration-handoff

Conversation

@TaprootFreak

Copy link
Copy Markdown
Contributor

Summary

Fixes the real cause of the post-account-merge "Wallet registration not complete" error in the RealUnit app.

When a new wallet signs up with an email that already belongs to an existing DFX account (account merge), and that account has no prior RealUnit/Aktionariat registration, GET /v1/realunit/registration correctly returns state = NewRegistration. The email-verification flow, however, called registerWallet (POST /v1/realunit/register/wallet) unconditionally — and that endpoint only adds a wallet to an existing registration, so the API rejects it with 400 "No RealUnit registration found". The user sees a red error even though the merge succeeded.

Root cause — runtime-confirmed (PROD)

App Insights for the reported incident:

  • GET /v1/realunit/registration200 (state=NewRegistration, userData present from existing KYC)
  • POST /v1/realunit/register/wallet400 {"message":"No RealUnit registration found"} (×4 retries)
  • recovery: the user reached the KYC registration form → POST /v1/realunit/register/complete201

DB confirmed the merged account had no RealUnitRegistration step until register/complete created it. 7-day breadth: 7× register/wallet 400 with this message (64% of register/wallet calls) — affects every merge into a DFX account without a prior RealUnit registration.

Fix (app-only, no API change)

KycEmailVerificationCubit._completeRegistration: when state == newRegistration, do not call registerWallet. The merge is already confirmed (JWT account changed), so hand back to the KYC flow — KycCubit routes NewRegistration to the full registration form (register/complete), exactly as the main KYC flow already does for that state (and as the runtime recovery proved works). addWallet / alreadyRegistered keep the existing inline registerWallet.

Tests

  • newRegistration (null userData) → Success/handoff, no registerWallet
  • newRegistration WITH userData present → Success/handoff, no registerWallet (reproduces the real bug: KYC firstname makes userData non-null)
  • addWallet → still calls registerWallet (unchanged)
  • reframed _mergeDetected retry test (transient registerWallet failure on AddWallet → retry → Success)

Test plan

  • flutter analyze clean
  • flutter test --exclude-tags golden2315 tests pass (full suite)
  • DEV end-to-end after merge: merge into a DFX account without RealUnit registration → no red error, lands on the registration form → register/complete

Replaces the earlier (incorrect) MergeProcessing PRs DFXswiss/api#3848 and #709, which addressed a propagation race that the runtime data showed never occurred.

@TaprootFreak TaprootFreak marked this pull request as ready for review June 9, 2026 12:53
@TaprootFreak TaprootFreak marked this pull request as draft June 9, 2026 13:11
@TaprootFreak

Copy link
Copy Markdown
Contributor Author

Superseded by the cleaner, CONTRIBUTING-aligned design (Option 2): the email-verification step now only confirms the merge and delegates ALL registration routing to KycCubit (single source of truth), instead of branching inline. See the replacement PR.

TaprootFreak added a commit that referenced this pull request Jun 9, 2026
## Summary
Fixes the post-account-merge "Wallet registration not complete" error
(red banner) in the RealUnit app, the CONTRIBUTING-aligned way.

When a new wallet signs up with an email that already belongs to an
existing **DFX** account (account merge) and that account has **no prior
RealUnit registration**, `GET /v1/realunit/registration` returns
`state=NewRegistration`. The email-verification step, however, called
`registerWallet` (`POST /register/wallet`) **unconditionally** — that
endpoint only *adds* a wallet to an **existing** registration, so the
API returns `400 "No RealUnit registration found"`.

## Root cause — runtime-confirmed (PROD App Insights)
- `GET /v1/realunit/registration` → **200** (state=NewRegistration,
userData present from existing KYC)
- `POST /v1/realunit/register/wallet` → **400 `{"message":"No RealUnit
registration found"}`** (×4 retries)
- recovery: the user reached the KYC registration form → `POST
/v1/realunit/register/complete` → **201**
- DB: the merged account had no `RealUnitRegistration` step until
`register/complete` created it. 7-day breadth: 7× this 400 (affects
every merge into a DFX account without a prior RealUnit registration).

## Fix (app-only) — single source of registration routing
The email-verification flow is reduced to its actual job: **confirm the
merge** (detect the JWT account change) and hand back to the KYC flow.
`KycCubit` is now the only place that interprets the registration
`state` and routes it (addWallet → link wallet, NewRegistration → full
registration form, AlreadyRegistered → forward) — per CONTRIBUTING.md
"API as Decision Authority". This removes the duplicated, unconditional
`register/wallet` call.

Dead code removed accordingly: `_completeRegistration`,
`_mergeDetected`, the `RealUnitRegistrationService` dependency, the
`KycEmailVerificationRegistrationFailure` state, and the now-unused i18n
key `registerEmailVerificationRegistrationFailed` (de + en).

## Tests
- email cubit (simplified): same account → Failure (link not visited);
changed account → Success (merge confirmed; no registration here); retry
(Failure → Success).
- `kyc_step_states_test` updated for the removed state.

## Test plan
- [x] `flutter analyze` clean
- [x] `flutter test --exclude-tags golden` — full suite passes (2312)
- [x] Coverage Floor Gate replicated locally — scoped **lines 100.0%**
(floor 100)
- [ ] DEV end-to-end: merge into a DFX account without RealUnit
registration → no red error → lands on the registration form →
register/complete

Supersedes #711 (minimal variant) and the earlier incorrect
MergeProcessing PRs DFXswiss/api#3848 + #709.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant