Skip to content

Name the address on the code screen, and offer another code - #19

Merged
JeroenDeDauw merged 1 commit into
separate-email-field-on-login-formfrom
code-screen-address-and-resend
Aug 22, 2026
Merged

Name the address on the code screen, and offer another code#19
JeroenDeDauw merged 1 commit into
separate-email-field-on-login-formfrom
code-screen-address-and-resend

Conversation

@alistair3149

Copy link
Copy Markdown
Member

Follows-up to #17

The screen asking for the code said nothing about where it went, offered no way to ask for another,
and no way back to the address box. A visitor who mistyped their address had nothing to see it by
and nowhere to go.

Name the address back, from the authentication session rather than the form, and add a button that
sends another code to it and a link back to the start of the login form. Starting the form again
already asks for an address rather than resuming the code screen, so only the way to it was missing.

The address is named whatever the allowlist made of it, so the screen still says the same for an
admitted address and one it has never heard of.

Asking for another code goes through the same use case as the first, so it is counted by the same
throttle, and it replaces the handle the session holds, so the code sent before it stops working.

The code box becomes optional. Required, it would have to be filled before the button asking for
another code could be pressed, which is exactly what a visitor without a working code needs to do.
An empty box is answered on instead, without spending one of the code's attempts.

Considered, omitted:

  • a countdown to when the code expires, which needs the issue time carried to the screen
  • rate limiting resends separately from first requests — the existing per-address burst limit of 3
    in 15 minutes already bounds them

Based on #17 rather than master, since it builds on the field that PR introduces.

AI-authored — Claude Code, Opus 5 (1M context); three-point ask from @alistair3149, no revisions; diff not yet human-reviewed; PHPCS, PHPStan and 734 tests pass locally, and the flow was driven end to end over HTTP — request, resend, old code rejected, new code logs in — but not viewed in a browser.

@codecov-commenter

codecov-commenter commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.23%. Comparing base (53a9db6) to head (2c1b26d).

Additional details and impacted files
@@                           Coverage Diff                            @@
##             separate-email-field-on-login-form      #19      +/-   ##
========================================================================
+ Coverage                                 84.88%   87.23%   +2.34%     
- Complexity                                  574      596      +22     
========================================================================
  Files                                        64       65       +1     
  Lines                                      1992     2100     +108     
========================================================================
+ Hits                                       1691     1832     +141     
+ Misses                                      301      268      -33     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@alistair3149
alistair3149 force-pushed the separate-email-field-on-login-form branch from 5e67582 to 53a9db6 Compare August 21, 2026 18:45
@alistair3149
alistair3149 force-pushed the code-screen-address-and-resend branch 3 times, most recently from bdf6980 to 7d13dab Compare August 21, 2026 19:18
The screen asking for the code said nothing about where it went, offered no way to
ask for another, and no way back to the address box. A visitor who mistyped their
address had nothing to see it by and nowhere to go.

Name the address back, from the authentication session rather than the form, and
offer two sentences under the code box: another code, and a way back to the start
of the login form. Starting the form again already asks for an address rather than
resuming the code screen, so only the way to it was missing.

What is named is what was typed, so the screen says the same for an admitted
address and one the allowlist has never heard of. It is named as a plaintext
parameter: the screen it appears on is parsed as wikitext, and an address is
nothing but a trimmed string, so given as an ordinary parameter one holding a
transclusion would fetch the page it names into the login screen for anyone at all
to read.

Asking for another code goes through the same use case as the first, so it is
counted by the same throttle, and it replaces the handle the session holds, so the
code sent before it stops working. A refusal used to answer by failing the login,
which threw the visitor off the screen and took the code they were holding with
them; now it leaves them there, withdraws the offer, and says why. A code sent
after a refusal offers it again.

Each sentence is one piece of markup rather than a prompt field beside a button
field. A form field is laid out as a block within a block, and a button is drawn as
a box whatever display it is given, so two of them will not read as one line. The
button in the sentence is real, but the field it belongs to is what the form
collects the press from, so that field stays described and is hidden instead.

The code box says what it takes: a one-time code, of the length the generator makes
them, digits only. A pattern is checked before the form is submitted whichever
button did it, so asking for another code is exempted from that check, and the box
itself is optional — required, it would have to be filled before the button asking
for another code could be pressed.

Considered, omitted:

* a countdown, either to the code expiring or to the allowance freeing, which would
  make this the extension's first JavaScript for something the withdrawn offer
  already says
* leading with the member route and folding the password form away
* inputmode on the code box, which HTMLForm passes no attribute through for

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@alistair3149
alistair3149 force-pushed the code-screen-address-and-resend branch from 7d13dab to 2c1b26d Compare August 21, 2026 19:59
@alistair3149

Copy link
Copy Markdown
Member Author
pr-2-code pr-3-refused

@alistair3149
alistair3149 marked this pull request as ready for review August 21, 2026 20:06
@JeroenDeDauw
JeroenDeDauw merged commit 69ced38 into separate-email-field-on-login-form Aug 22, 2026
6 checks passed
@JeroenDeDauw
JeroenDeDauw deleted the code-screen-address-and-resend branch August 22, 2026 12:47
JeroenDeDauw pushed a commit that referenced this pull request Aug 22, 2026
* Ask for the member's address in a box of its own

The code route borrowed the login form's username box. A field several providers
describe is labelled by the first of them, and this one is not it, so the address
box was labelled "Username", placeholded "Enter your username" and autocompleted
from the username the browser had saved. The messages meant to say otherwise,
memberaccess-auth-email-label and -help, never reached the page. The button sending
the code also sat above the button it is an alternative to, styled as the form's
primary button beside the one that already was.

Ask for the address in a field of this request's own, typed as one so that a phone
offers the keyboard for it and a browser fills it from the right place, below the
password form and behind a divider, with a button that is progressive without being
primary.

A box of its own means the request declares no username, so a code request names no
account to MediaWiki and is counted against the client IP rather than against one
address. Telling one address from another is left to the extension's own throttle,
which is the tighter of the two. Declaring a username anyway would put a second
answer on a form that already has the username box, and two requests naming
different accounts is a conflict MediaWiki raises rather than resolves.

Considered, omitted:

* leading with the member route and folding the password form away, which suits a
  wiki whose logins are mostly members but hides the staff route
* a heading over the section, which the divider and the field's own label already
  say
* revisiting the wiki-wide badloginperuser captcha concession, which was made
  because the address sat in the field ConfirmEdit reads as the login subject and
  may no longer be needed now that it does not

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Name the address on the code screen, and offer another code (#19)

The screen asking for the code said nothing about where it went, offered no way to
ask for another, and no way back to the address box. A visitor who mistyped their
address had nothing to see it by and nowhere to go.

Name the address back, from the authentication session rather than the form, and
offer two sentences under the code box: another code, and a way back to the start
of the login form. Starting the form again already asks for an address rather than
resuming the code screen, so only the way to it was missing.

What is named is what was typed, so the screen says the same for an admitted
address and one the allowlist has never heard of. It is named as a plaintext
parameter: the screen it appears on is parsed as wikitext, and an address is
nothing but a trimmed string, so given as an ordinary parameter one holding a
transclusion would fetch the page it names into the login screen for anyone at all
to read.

Asking for another code goes through the same use case as the first, so it is
counted by the same throttle, and it replaces the handle the session holds, so the
code sent before it stops working. A refusal used to answer by failing the login,
which threw the visitor off the screen and took the code they were holding with
them; now it leaves them there, withdraws the offer, and says why. A code sent
after a refusal offers it again.

Each sentence is one piece of markup rather than a prompt field beside a button
field. A form field is laid out as a block within a block, and a button is drawn as
a box whatever display it is given, so two of them will not read as one line. The
button in the sentence is real, but the field it belongs to is what the form
collects the press from, so that field stays described and is hidden instead.

The code box says what it takes: a one-time code, of the length the generator makes
them, digits only. A pattern is checked before the form is submitted whichever
button did it, so asking for another code is exempted from that check, and the box
itself is optional — required, it would have to be filled before the button asking
for another code could be pressed.

Considered, omitted:

* a countdown, either to the code expiring or to the allowance freeing, which would
  make this the extension's first JavaScript for something the withdrawn offer
  already says
* leading with the member route and folding the password form away
* inputmode on the code box, which HTMLForm passes no attribute through for

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

3 participants