Separate second-factor verification and delivery from auth (#40)

This commit is contained in:
Stephan D committed 2026-09-12 20:36:35 +02:00
1 parent 12a38cd654
commit ecb63b61c6
33 files changed
+1772 -123

No files matched your search

+44
View File
@@ -536,3 +536,47 @@ frontend API URL/public client before enabling real auth.
Delivered in [PR #39](https://git.sendico.io/tech/sxchnge/pulls/39). Merge order: #35 → #37 → #39. The auth branch incorporates notification completion commit `4b14649`; only the delivery-log append conflicted, and both task records are preserved.
## Dedicated second-factor service (#40)
Task [#40](https://git.sendico.io/tech/sxchnge/issues/40), branch `twofactor-40`,
based on main after merged PR #39. Primary module: twofactor; secondary modules:
auth, verification purpose definitions, notification templates and Flutter auth.
`product/twofactor` now owns challenge issuance/delivery, verified destinations,
preferences, attempt/cooldown limits and single-use proofs. It reuses the
Sendico-derived verification store at the existing pinned revision. No new
Sendico handler or private messaging code was copied. Auth owns credentials,
pending JWTs and session creation; signup activation remains in `auth/flow`.
The service's `Complete` transaction commits code verification, proof consumption
and the owner's session write together. Review fixed rejected-attempt rollback,
ensured failed session writes preserve retryability, retained activation replay
key compatibility and removed the unused verification-store injection from auth
HTTP. A profile write serializes consumption against preference changes.
Authenticated APIs enroll additional verified emails and change the preferred
factor only after verifying the current factor. Unsupported channels fail closed.
Flutter's shared DTO/mapper/service adapter sends the server challenge ID with
the pending JWT, preserves resend keys after failure and rejects unknown channels.
No widgets or provider/analytics boundaries changed. Existing login journey
measurement and error/recovery UI remain in use; settings UI integration is not
part of this separation.
Validation passed: `make test` (all Go race suites and `make test-frontend`),
`make lint-backend`, `flutter analyze` in `frontend/packages/sxchnge_auth`, and
Dart format verification for all four changed Dart files. New real Mongo tests
cover single-use proofs, customer/purpose/context isolation, delivery retries,
committed failed guesses, expiry, inactive accounts, operation rollback,
concurrent completion, verified enrollment, preference selection and old-proof
invalidation. The updated signup/login test covers the full auth boundary;
transport and architecture tests cover scope injection and domain dependencies.
Frontend tests cover challenge binding, resend recovery and unsupported channels.
No live email or optional security scan was run.
See [ownership, Sendico provenance, HTTP contract and rollout](architecture/two-factor.md).
Deploy backend and client together, load `twofactor.code` revision 1, and restart
previously pending logins after rollout. Email is the implemented channel.
Existing settings screens still use preview adapters; SMS/push/TOTP/passkeys,
factor removal/recovery, payout integration and a separate process are not
implemented. Successful-commit response loss still requires login restart;
notification queue acceptance is not inbox delivery.