Skip to content

docs(identity): document the profile ETag/If-Match precondition - #246

Open
marcelo-maciel wants to merge 1 commit into
fullstackhero:mainfrom
marcelo-maciel:docs/identity-profile-concurrency
Open

docs(identity): document the profile ETag/If-Match precondition#246
marcelo-maciel wants to merge 1 commit into
fullstackhero:mainfrom
marcelo-maciel:docs/identity-profile-concurrency

Conversation

@marcelo-maciel

@marcelo-maciel marcelo-maciel commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Documents the optimistic-concurrency precondition added to PUT /identity/profile in
fullstackhero/dotnet-starter-kit#1366 (fixes fullstackhero/dotnet-starter-kit#1359).

Identity module page

New Profile concurrency section under Public API highlights: what the lost update looked
like, the ETag/If-Match exchange with a short HTTP sample, and the details a caller actually
trips over:

  • the header is optional, so existing callers are unaffected, and If-Match: * is accepted
  • a weak validator never matches, because If-Match mandates the strong comparison function
  • a malformed header answers 400, not 412 (a 412 would trap a client in a retry loop it
    cannot win)
  • the precondition runs before any storage call, so a rejected update never orphans an uploaded
    avatar nor clears the current one
  • clients should refetch and retry once on 412, since the stamp also rotates on writes a user
    does not think of as profile edits (password change, new avatar, failed sign-in)
  • the CORS requirement: the contract is invisible to a browser on another origin without the
    ETag exposure and the if-match allow-entry

The two /profile rows in the endpoints table now mention the ETag and the If-Match / 412
behaviour.

Changelog

One dated entry for the fix plus a second for the CORS change, since anyone who replaced the
kit's CORS policy with their own has to carry the ETag exposure and the if-match allow-entry
or the precondition silently degrades back to a lost update.

npx astro check: 0 errors, 0 warnings (21 pre-existing hints).

The changelog heading is dated 2026-08-17, the day the code PR opened, following docs#239. Happy to
move it to the merge date if the code PR lands later.

`PUT /identity/profile` gained an optimistic concurrency precondition: `GET /profile`
returns the user's `ConcurrencyStamp` as a strong `ETag`, `PUT` honours `If-Match`, and
a stale token is answered with `412` instead of overwriting the newer write.

Documents the optional-header behaviour, the `*` and weak-validator rules, why a
malformed header is a `400`, the guard running ahead of any storage call, and the
retry-once guidance for clients (the stamp rotates on writes a user does not perceive
as profile edits). Also notes the CORS requirement, since the contract is invisible to
a browser on another origin without the `ETag` exposure and the `if-match` allow-entry.

Accompanies fullstackhero/dotnet-starter-kit#1366.
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.

Lost update on PUT /identity/profile: no concurrency token on a full-representation update

1 participant