Several email addresses, and what a plugin could honestly govern there #145

Closed
opened 2026-09-09 10:48:01 +00:00 by tiagoagueda · 1 comment
Owner

Observation

multiple e-mails shoud became an internal plugin as we did to the phone numbers and play the
same role on the recovery of the user acount

What exists

All of it, except the plugin. Several addresses per account, exactly one primary, each
verified independently, unique across the instance, and already the recovery route — that is
allauth's EmailAddress, and it is what #90 copied when telephone numbers were built:

Email addresses already work the way this asks: allauth's EmailAddress gives an account
several, exactly one primary, each verified independently, and unique across the
instance. So there is a shape to copy, and its edges are already known.

Settings → Account lists them with their primary and verified state and links to allauth's
page for adding, removing and changing which is primary. recovery_routes() returns email
whenever a transport is selected. So the capability the suggestion asks for is not missing;
what is missing is the plugin framing around it.

What this asks for

The same treatment phone numbers got: an internal plugin, switchable, self-contained.

Worth being careful about

The model is not Postulo's, and that changes what a plugin can honestly do.
EmailAddress belongs to allauth.account, with allauth's migrations behind it and
allauth's own flows reading it: verification, password reset, sign-in by address, social
account linking. Phone numbers replaced a CharField Postulo owned outright; addresses would
mean a plugin taking over a library's core model, which is a different proposition and not a
safe one.

What a plugin could govern is the page, not the data. Off would mean the interface
offers one address — the primary, which is what user.email already is — and stops offering
the management page. That is coherent, it matches #90's "off shows the primary" exactly, and
it deletes nothing because it owns nothing. It is also a much smaller feature than it sounds,
and worth being honest that the visible change is a link disappearing.

Off must never remove the last way back in. For phone numbers, switching the feature off
loses nothing that matters. For addresses it could: if somebody keeps a second address
because the first is a work account they are about to lose, hiding the page does not remove
the address but does remove their ability to promote it when they need to. #104's lock exists
for exactly this shape of mistake, one level up.

The verified flag is what makes any of this a recovery route, and it is allauth's, set by
allauth's flow. Any plugin around this inherits that flow rather than reimplementing it —
which is an argument for the gate being presentation-only, since a plugin that could not
verify an address could not honestly own one.

So the useful question this raises is not about email. It is whether governing a page
is a legitimate thing for a feature plugin to do at all, given #90 established that a feature
governs what Postulo offers and uses. If it is, this is a small change; if a feature must own
its data to be a feature, then addresses cannot be one and the answer is to say so and leave
allauth's model alone.

The parallel worth keeping is the other way round. Numbers were built to match addresses;
what would improve both is the unverified half — addresses have verification and numbers do
not, which is the gap that stops numbers being a recovery route. That work is the
prerequisite for the telephone side and needs nothing from this issue.

## Observation > multiple e-mails shoud became an internal plugin as we did to the phone numbers and play the > same role on the recovery of the user acount ## What exists **All of it, except the plugin.** Several addresses per account, exactly one primary, each verified independently, unique across the instance, and already the recovery route — that is allauth's `EmailAddress`, and it is what #90 copied when telephone numbers were built: > Email addresses already work the way this asks: allauth's `EmailAddress` gives an account > several, exactly one `primary`, each `verified` independently, and unique across the > instance. So there is a shape to copy, and its edges are already known. *Settings → Account* lists them with their primary and verified state and links to allauth's page for adding, removing and changing which is primary. `recovery_routes()` returns `email` whenever a transport is selected. So the capability the suggestion asks for is not missing; what is missing is the plugin framing around it. ## What this asks for The same treatment phone numbers got: an internal plugin, switchable, self-contained. ## Worth being careful about **The model is not Postulo's, and that changes what a plugin can honestly do.** `EmailAddress` belongs to `allauth.account`, with allauth's migrations behind it and allauth's own flows reading it: verification, password reset, sign-in by address, social account linking. Phone numbers replaced a `CharField` Postulo owned outright; addresses would mean a plugin taking over a library's core model, which is a different proposition and not a safe one. **What a plugin could govern is the *page*, not the data.** *Off* would mean the interface offers one address — the primary, which is what `user.email` already is — and stops offering the management page. That is coherent, it matches #90's "off shows the primary" exactly, and it deletes nothing because it owns nothing. It is also a much smaller feature than it sounds, and worth being honest that the visible change is a link disappearing. **Off must never remove the last way back in.** For phone numbers, switching the feature off loses nothing that matters. For addresses it could: if somebody keeps a second address because the first is a work account they are about to lose, hiding the page does not remove the address but does remove their ability to promote it when they need to. #104's lock exists for exactly this shape of mistake, one level up. **The verified flag is what makes any of this a recovery route**, and it is allauth's, set by allauth's flow. Any plugin around this inherits that flow rather than reimplementing it — which is an argument for the gate being presentation-only, since a plugin that could not verify an address could not honestly own one. **So the useful question this raises is not about email.** It is whether *governing a page* is a legitimate thing for a feature plugin to do at all, given #90 established that a feature governs what Postulo offers and uses. If it is, this is a small change; if a feature must own its data to be a feature, then addresses cannot be one and the answer is to say so and leave allauth's model alone. **The parallel worth keeping is the other way round.** Numbers were built to match addresses; what would improve both is the *unverified* half — addresses have verification and numbers do not, which is the gap that stops numbers being a recovery route. That work is the prerequisite for the telephone side and needs nothing from this issue.
tiagoagueda added this to the 0.3.0 milestone 2026-09-09 10:48:01 +00:00
Author
Owner

The issue said the useful question was not about email, and it was right — so this answers
that one, and the feature falls out of it.

whether governing a page is a legitimate thing for a feature plugin to do at all … if a
feature must own its data to be a feature, then addresses cannot be one

It is legitimate, and phone-numbers is the precedent rather than the contrast. Off does
not delete a number either: it shows and uses the primary one and the rest stay recorded. A
feature governs what Postulo offers and uses — which is what both of these do. The
mechanism is the same; only the ownership differs, and this one owns nothing at all.

So the model stays allauth's. Its migrations are behind it and its flows read it —
verification, password reset, signing in by address, linking a social account — and, as the
issue put it, a plugin that could not verify an address could not honestly own one. Off means
the primary address is offered and the management page is not.

The warning that turned into a rule

if somebody keeps a second address because the first is a work account they are about to
lose, hiding the page does not remove the address but does remove their ability to promote
it when they need to. #104's lock exists for exactly this shape of mistake, one level up.

Taken literally. There is a floor under the policy, and the page is never withheld from:

  • an account that already has more than one address — it is already relying on this;
  • an account whose only address is unverified — the page is what fixes exactly that.

Below the policy rather than beside it: an administrator's decision still applies to everyone
it can apply to without stranding them. Both floors are tested by the failure they prevent.

Small things, said rather than implied

The visible change is a link disappearing. The issue asked for that honesty and the
plugin's own description carries it: "Nothing is deleted: the addresses stay, and an account
that already has more than one keeps the page."

The plugin does not ask whether it is switched on. That would be a plugin marking its own
homework, so the declaration is the plugin and the decision is postulo.accounts.addresses —
the same division phone-numbers uses, and a test holds both halves to it.

docs/PLUGINS.md now says the rule for anybody writing a feature: it need not own its
data, and if switching it off could cost somebody something they cannot get back, that needs
a floor.

The parallel the other way round is untouched, as the issue said it should be: verifying
a telephone number is what would make numbers a recovery route, and it needs nothing from
here.

8 tests, 2 strings in all 39 European catalogues. Shipped in 384aa98 on 0.3.0, with
main kept level.

The issue said the useful question was not about email, and it was right — so this answers that one, and the feature falls out of it. > whether *governing a page* is a legitimate thing for a feature plugin to do at all … if a > feature must own its data to be a feature, then addresses cannot be one **It is legitimate, and `phone-numbers` is the precedent rather than the contrast.** Off does not delete a number either: it shows and uses the primary one and the rest stay recorded. A feature governs *what Postulo offers and uses* — which is what both of these do. The mechanism is the same; only the ownership differs, and this one owns nothing at all. **So the model stays allauth's.** Its migrations are behind it and its flows read it — verification, password reset, signing in by address, linking a social account — and, as the issue put it, a plugin that could not verify an address could not honestly own one. Off means the primary address is offered and the management page is not. ## The warning that turned into a rule > if somebody keeps a second address because the first is a work account they are about to > lose, hiding the page does not remove the address but does remove their ability to promote > it when they need to. #104's lock exists for exactly this shape of mistake, one level up. Taken literally. There is a floor under the policy, and the page is **never** withheld from: - an account that already has **more than one address** — it is already relying on this; - an account whose only address is **unverified** — the page is what fixes exactly that. Below the policy rather than beside it: an administrator's decision still applies to everyone it can apply to without stranding them. Both floors are tested by the failure they prevent. ## Small things, said rather than implied **The visible change is a link disappearing.** The issue asked for that honesty and the plugin's own description carries it: *"Nothing is deleted: the addresses stay, and an account that already has more than one keeps the page."* **The plugin does not ask whether it is switched on.** That would be a plugin marking its own homework, so the declaration is the plugin and the decision is `postulo.accounts.addresses` — the same division `phone-numbers` uses, and a test holds both halves to it. **`docs/PLUGINS.md` now says the rule for anybody writing a feature:** it need not own its data, and if switching it off could cost somebody something they cannot get back, that needs a floor. **The parallel the other way round is untouched**, as the issue said it should be: verifying a telephone number is what would make numbers a recovery route, and it needs nothing from here. 8 tests, 2 strings in all 39 European catalogues. Shipped in `384aa98` on `0.3.0`, with `main` kept level.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#145
No description provided.