Enhancement Proposal

Proposal: Authenticator app and push MFA

Passkeys stay the phishing-resistant primary (ADR-0020), TOTP the offline fallback — but the factor the incumbents deploy fleet-wide is push approve/deny in a first-party app. This adds that app — number matching mandatory, approvals signed — plus a Temporary Access Pass for bootstrap.

Motivation

Push MFA is the default workforce factor at the incumbents (Microsoft Authenticator, Okta Verify); an MFA story that stops at TOTP loses that comparison. ADR-0020 scoped v1 to WebAuthn and TOTP, amr/acr stamped for edge enforcement; proposal 0011 built the delivery seam push would ride. Push also has a public failure mode (MFA-fatigue bombing) a new entrant must design out, not patch in — and neither factor closes the onboarding gap: how does a passwordless user enroll a first strong factor? This proposal answers all three.

Design

  1. A first-party authenticator app, open-source, with push approve/deny as its core factor. The app also acts as a TOTP generator (the fallback that works offline) and composes with platform passkeys rather than replacing them — passkeys stay the phishing-resistant primary (ADR-0020); push covers what they don't: step-up prompts on a session already past login, legacy devices without authenticators, approve-from-another-device.

  2. Number matching is mandatory, not optional. Every push challenge displays a code at the login surface that the user must enter or select in the app — blind tap-to-approve is refused by design, because MFA-fatigue bombing defeated it industry-wide. Deny-with-reason ("this wasn't me") is a first-class response feeding the risk pipeline (ADR-0031) and attack protection (proposal 0021) as a high-signal event.

  3. Enrollment is a Modgud ceremony; the device becomes a registered authenticator. QR / deep-link enrollment runs behind the multi-step AuthenticationMethod seam at Modgud (ADR-0009). The device holds a hardware-backed keypair (keystore / secure enclave) and signs every push response — approval is a cryptographic assertion, not a button press over TLS. The device record feeds device trust (ADR-0031); an amr value distinct from TOTP and WebAuthn lets acr policy distinguish factor strength — ADR-0020's model unchanged.

  4. Push transport rides the notification seam, with an honest vendor wrinkle. Delivery is a new channel type on proposal 0011's trait, targeting platform push (APNs/FCM) — which fails the ADR-0008 control-resilience test: no self-hostable path into Apple's and Google's push networks. That is named, not hidden: push is never the only path — the app polls for pending challenges on open, TOTP always works offline, and an unanswered push times out to deny within a stated budget (ADR-0039 registry entry). Self-hostable push (ntfy/UnifiedPush) is an open question, not a v1 promise.

  5. A Temporary Access Pass (TAP) bootstraps enrollment. A time-boxed, limited-use credential an admin — or delegated helpdesk, proposal 0016 — issues so a new or recovering user can enroll a first strong factor without ever holding a password: the gap TOTP and WebAuthn leave open. TAP is an AuthenticationMethod (ADR-0015) with forced expiry and use-count, satisfies only enrollment-grade acr (never step-up), and every issue and use is an event (ADR-0022).

  6. Everything is evented and budgeted. Challenge issued / approved / denied / timed-out, enrollments, TAP lifecycle — all on the stream (ADR-0022) for audit and risk; push round-trip latency is a freshness-plane signal (proposal 0012).

Alternatives considered

  • SMS/voice as the push substitute. Rejected as flagship — SIM-swap-weak; they exist as explicit low-assurance methods per ADR-0015, never the lead.
  • Third-party TOTP apps only. Already supported and stays supported — but no push, no deny signal, no number matching.
  • A FIDO2-only strategy. Passkeys remain primary, but push covers real surfaces passkeys don't: step-up on an established session, legacy devices, delegated approval from another device.
  • Building on a hosted MFA vendor. Fails the ADR-0008 control-resilience test as the only path — the same call proposal 0021 made for bot detection.

Graduation criteria

  • Push with number matching works end-to-end against the reference app; a blind approve is impossible — asserted as an abuse-case test (ADR-0028).
  • An MFA-fatigue burst (repeated pushes at one user) trips attack-protection throttling (proposal 0021) — abuse-case tested.
  • Deny-with-reason lands in the risk pipeline as a scored signal.
  • TAP enrolls a first factor and cannot satisfy step-up acr.
  • An unanswered push times out to deny within the registered budget; a forged approval is rejected by signed-response verification.

Backward compatibility

  • New amr value(s) and TAP ride existing seats — ADR-0015 methods, ADR-0020 claims, proposal 0011 channels — no token-format change.
  • The app protocol is versioned from v0 like every external format (ADR-0003 discipline).

Open questions

  • Is a self-hostable push transport (UnifiedPush/ntfy) viable alongside APNs/FCM?
  • Does the authenticator app double as a passkey holder, or stay factor-only?
  • TAP default lifetime and use-count.
  • iOS/Android release cadence vs the server's — the app is a separately-versioned artifact.