Proposal 01: pluggable two-factor provider seam

Design sketch only. Re-read the current frappe/twofactor.py, auth imports, login client, and test suite before implementing. This document does not claim the current branches expose this contract.

Goal

Allow core or an app to provide a reviewed non-OTP second-factor method without monkeypatching import-bound authentication functions, while leaving existing OTP App/SMS/Email behavior unchanged when no provider is selected.

Proposed contract

A provider needs three responsibilities:

The exact hook shape, conflict policy, provider validation, client dispatch, and naming are maintainer decisions. Provider lookup must reject ambiguous/malformed registrations, and per-user fallback must not silently downgrade an enrolled passkey user around the app/native passkey policy.

Implementation checklist

Passkey-specific warning

A generic provider seam is not sufficient to claim native passkey support. The second-factor login veto, one-time OTP fallback marker, narrow Administrator exemption, keyed password-hash version, and transactional credential updates remain mandatory acceptance criteria in VALIDATE.md.