Doc: Loader auth-independent for link checks; email-sync rule rationale

This commit is contained in:
Moritz 2026-02-03 15:00:14 +01:00
parent 4ea31f0f37
commit 4e6b7305b6
Signed by: moritz
GPG key ID: 1020A035E5DD0824
2 changed files with 9 additions and 7 deletions

View file

@ -4,7 +4,7 @@
2. **DB constraints** - Prevent duplicates within same table (users.email, members.email) 2. **DB constraints** - Prevent duplicates within same table (users.email, members.email)
3. **Custom validations** - Prevent cross-table conflicts only for linked entities 3. **Custom validations** - Prevent cross-table conflicts only for linked entities
4. **Sync is bidirectional**: User ↔ Member (but User always wins on link) 4. **Sync is bidirectional**: User ↔ Member (but User always wins on link)
5. **Linked member email change** - When a member is linked, only administrators or the linked user may change that member's email (Member resource validation `EmailChangePermission`). This keeps email sync under control and prevents non-admins from changing another user's linked member email. 5. **Linked member email change** - When a member is linked, only administrators or the linked user may change that member's email (Member resource validation `EmailChangePermission`). Because User.email wins on link and changes sync Member → User, allowing anyone to change a linked member's email would overwrite that user's account email; this rule keeps sync under control.
--- ---

View file

@ -3,13 +3,15 @@ defmodule Mv.EmailSync.Loader do
Helper functions for loading linked records in email synchronization. Helper functions for loading linked records in email synchronization.
Centralizes the logic for retrieving related User/Member entities. Centralizes the logic for retrieving related User/Member entities.
## Authorization ## Authorization-independent link checks
This module runs systemically and uses the system actor for all operations. All functions use the **system actor** for the load. Link existence
This ensures that email synchronization always works, regardless of user permissions. (linked vs not linked) is therefore determined **independently of the
current request actor**. This is required so that validations (e.g.
All functions use `Mv.Helpers.SystemActor.get_system_actor/0` to bypass `EmailChangePermission`, `EmailNotUsedByOtherUser`) can correctly decide
user permission checks, as email sync is a mandatory side effect. "member is linked" even when the current user would not have read permission
on the related User. Using the request actor would otherwise allow
treating a linked member as unlinked and bypass the permission rule.
""" """
alias Mv.Helpers alias Mv.Helpers
alias Mv.Helpers.SystemActor alias Mv.Helpers.SystemActor