Cap the profile email-address conflict answer

Changing the profile address asks whether another account already holds
it, and the answer is 409 versus 200 — an existence check over every
address on the instance, open to any signed-in caller. Neither route
that reaches it had a ceiling of any kind and the API wrapper supplies
no default, so the only bound on a sweep was the network.

Both routes now share one per-account bucket, ten an hour, charged
before the question is asked so a refused caller learns nothing. Only a
request whose address actually differs from the one on file is counted,
so re-saving a settings form that carries the unchanged address stays
free. The refusal is the standard 429 with Retry-After and the
X-RateLimit triple, carries `profile.update.emailRateLimited`, and is
published on both operations.
This commit is contained in:
Marc-André Bombeck committed 2026-09-11 14:05:25 +02:00
1 parent 6a5fb338b1
commit fe420f76d8
17 files changed
+596 -181

No files matched your search

+1
View File
@@ -250,6 +250,7 @@ export const ERROR_CODE_CATALOGUE: Readonly<Record<string, readonly string[]>> =
practitioner: ["practitioner.invalid"],
profile: [
"profile.update.emailInUse",
"profile.update.emailRateLimited",
"profile.update.invalidBody",
"profile.update.nothingSaved",
],