Add reusable two-factor verification for login and money operations (#32)
This commit is contained in:
1 parent
b7a58b1a87
commit
fb40f860d2
41 files changed
+2439
-43
No files matched your search
@@ -321,3 +321,40 @@ above describe delivery-time state and are superseded by this integration record
|
||||
|
||||
Validation of the combined tree: all 115 frontend tests and app analysis passed;
|
||||
diff checks passed. Branches were retained. No checks were bypassed.
|
||||
|
||||
## Reusable two-factor verification — task #32
|
||||
|
||||
Branch `two-factor-32` adds a SXCHNGE-designed, theme-based code page reused by
|
||||
login, top-up, exchange, payout and verified profile enable/disable. EN/RU copy,
|
||||
one accessible input, keyboard/paste support, resend cooldown, invalid/expired/
|
||||
locked/unavailable recovery and cancellation preserve context. Transaction
|
||||
verification retains its reviewed funds movement and fees. No Sendico UI or code
|
||||
was copied for this feature.
|
||||
|
||||
Shared auth owns explicit DTOs, mappers, domain models, service contracts and
|
||||
providers. Method-aware contracts distinguish email and authenticator challenges;
|
||||
the initial email fixture uses code `123456`, sends no email, defaults off and
|
||||
resets on reload. Real TOTP enrollment, method selection, delivery, recovery and
|
||||
backend enforcement remain integration work. Mobile can reuse the page and
|
||||
providers with its own router/localization and service adapters.
|
||||
|
||||
Login stays pending until approval is consumed. The dummy wallet consumes a
|
||||
purpose/quote-bound, expiring, one-use approval before execution. Concurrent
|
||||
idempotent retries debit once; expired quotes require fresh review; uncertain
|
||||
outcomes retain reconciliation. Timers stop on route/app disposal and late
|
||||
responses are ignored. Settings update only after service confirmation. Analytics
|
||||
retains parent journey correlation and distinguishes verification from actual
|
||||
login/settings/settlement outcomes; codes, grants and targets never enter events.
|
||||
|
||||
Frontend and UX review covered the complete task diff. Validation passed:
|
||||
`dart format --output=none --set-exit-if-changed` for all 34 changed Dart files;
|
||||
`flutter analyze` in app, sxchnge_auth, sxchnge_wallet and sxchnge_analytics;
|
||||
`make test-frontend` (147 tests); `flutter build web` (including Wasm dry run);
|
||||
`git diff --check`. Browser checks at 1280×720 and 390×844 verified themed layout,
|
||||
invalid-code recovery, keyboard entry and confirmed settings. Widget tests cover
|
||||
Russian at 320px/1.6× text scale and all money entry points. No security scan was
|
||||
requested or run. Earlier validation failures were corrected, including ARB
|
||||
metadata handling, disabled-policy latency, route timer disposal and lint findings.
|
||||
|
||||
See [the UX and measurement contract](ux/two-factor.md) and
|
||||
[shared auth integration guide](../frontend/packages/sxchnge_auth/README.md).
|
||||
@@ -0,0 +1,68 @@
|
||||
# Two-factor verification — task #32
|
||||
|
||||
Use a SXCHNGE-designed challenge page: themed security icon, clear purpose,
|
||||
operation summary when moving money, one labeled six-digit input, Verify and
|
||||
continue, contextual delivery recovery and Cancel. Avoid six separate focus
|
||||
boxes, automatic submission, repeated banners and raw service error text.
|
||||
|
||||
Email is the initial service fixture. Method is carried in settings and challenge
|
||||
DTO/model contracts. Authenticator/TOTP challenges use their own instruction and
|
||||
have no email target or resend controls. The reusable shared page accepts labels
|
||||
and an optional summary, so clients supply their own localization and context.
|
||||
Authenticator enrollment/secret provisioning is a future backend capability;
|
||||
it is not offered as a working setting without that contract. No Sendico UI or
|
||||
code is copied. Its pending-login concept informed the separation of steps.
|
||||
|
||||
Profile shows current protection status and verified enable/disable actions.
|
||||
Cancel changes nothing. No optimistic protection toggle: the service result
|
||||
must confirm the new setting. The existing stub has one account and resets on
|
||||
reload. Production settings must be account-scoped and authenticated.
|
||||
|
||||
Login first validates credentials. A pending result is not a session or login
|
||||
success; complete it only after consuming a matching approval. Clear the password
|
||||
before opening the challenge. Cancel returns to login without successful state.
|
||||
|
||||
All top-ups, exchanges and payouts request a factor when service policy requires
|
||||
it. The challenge binds to the quote ID; its one-use grant is checked by the
|
||||
operation adapter before money moves. Editing, expired quotes, mismatched grants
|
||||
and reuse cannot authorize a different transaction. Existing idempotency and
|
||||
unknown-outcome reconciliation remain authoritative. Cancel returns to the review
|
||||
with the draft preserved. Expired quotes require fresh review and confirmation.
|
||||
|
||||
Invalid code preserves context; retry stays in the same challenge. Email resends
|
||||
have service-owned cooldowns and replace the previous challenge. Expired code,
|
||||
rate limiting and unavailable service have localized recovery. Verification and
|
||||
resend disable duplicate actions, clean up timers/controllers on disposal, and
|
||||
ignore late results. Pasted codes, keyboard submission, live errors and EN/RU
|
||||
mobile layouts must work.
|
||||
|
||||
Measurement extends existing typed journeys with factor delivery/verification and
|
||||
settings outcome steps. Login completion waits for the final login result;
|
||||
transaction completion still waits for settlement. Cancelled challenges do not
|
||||
claim success. No code, email target, challenge ID, grant, secret, amount or
|
||||
recipient enters analytics or route URLs. Events retain the simulated flag.
|
||||
Actual MFA enforcement, OTP delivery/validation, enrollment and recovery must run
|
||||
on the backend before production use.
|
||||
|
||||
## Measurement and review evidence
|
||||
|
||||
- The existing login/transaction attempt owns verification and retries. A factor
|
||||
success is an intermediate step; only completed login, confirmed settings save
|
||||
or transaction settlement can complete its parent journey.
|
||||
- `factor_challenge` measures settings/transaction policy checks and challenge
|
||||
creation failures. `factor_delivery` measures email resends;
|
||||
`factor_verification` measures code checks and explicit cancellation;
|
||||
`factor_settings` measures the confirmed setting update. Login's existing
|
||||
credential step includes initial challenge creation and its failures.
|
||||
- Product/support can compare failure and resend rates by typed step, and measure
|
||||
completion/duration per distinct parent journey. Retries remain in that journey;
|
||||
its existing timeout/explicit-navigation rules close abandoned attempts. Pending
|
||||
money operations continue through the existing settlement recorder.
|
||||
- Browser review: desktop 1280×720 and mobile 390×844; theme roles, heading, input,
|
||||
buttons, invalid-code recovery, keyboard submission and confirmed setting status.
|
||||
Widget tests additionally cover Russian at 320px and 1.6× text scale, all money
|
||||
entry points, cancellation, service errors and missing route context.
|
||||
- Analytics tests check correlation, one terminal login outcome, cancellation,
|
||||
challenge creation failure and absence of codes in event payloads. Stub policy
|
||||
remains simulated even if a credentials adapter returns a non-simulated result.
|
||||
Backend/cross-device outcomes remain unavailable until services are integrated.
|
||||
Reference in new issue
Block a user