@startuml update-username !include ../../../pipeline/diagrams/biergarten-weizen-theme.puml skinparam sequenceMessageAlign center skinparam maxMessageSize 200 title User Authentication Flow - Update Username actor User participant "API\nController" as API participant "MediatR pipeline\n(ValidationBehavior)" as Mediator box "Handler Layer" #F1F3EA participant "UpdateUsernameHandler" as UpdateUsernameHandler participant "UserManager" as UserMgr end box box "Repository / Cross-slice" #DBEEDD participant "DapperUserStore\n(IUserStore/IUserPasswordStore/\nIUserEmailStore)" as UserStore end box database "SQL Server" as DB note over UserMgr ASP.NET Core Identity's UserManager replaces the deleted AuthRepository: handlers no longer issue SQL or call Argon2 directly, they delegate to UserManager, which in turn calls DapperUserStore (persistence) and Argon2PasswordHasher (IPasswordHasher). end note User -> API: PATCH /api/auth/username\n{newUsername}\n(requires Bearer access token) activate API API -> Mediator: Send(UpdateUsernameCommand(\n GetAuthenticatedUserId(), newUsername)) activate Mediator note right of Mediator ValidationBehavior runs UpdateUsernameValidator (same format rules as registration) end note alt Validation fails Mediator -> API: throws FluentValidation.ValidationException API -> User: 400 Bad Request else Validation succeeds Mediator -> UpdateUsernameHandler: Handle(command) activate UpdateUsernameHandler UpdateUsernameHandler -> UserMgr: FindByIdAsync(userAccountId) activate UserMgr UserMgr -> UserStore: FindByIdAsync(userAccountId) activate UserStore UserStore -> DB: SELECT ...\nFROM dbo.UserAccount\nWHERE UserAccountID = @Id activate DB DB --> UserStore: row or null deactivate DB UserStore --> UserMgr: ApplicationUser or null deactivate UserStore UserMgr --> UpdateUsernameHandler: ApplicationUser or null deactivate UserMgr alt Account not found UpdateUsernameHandler -> Mediator: throw NotFoundException Mediator -> API: propagate API -> User: 404 Not Found else Account found UpdateUsernameHandler -> UserMgr: SetUserNameAsync(user, newUsername) activate UserMgr UserMgr -> UserStore: FindByNameAsync(newUsername) note right of UserMgr Uniqueness check before the UPDATE. end note UserMgr -> UserStore: UpdateAsync(user) UserStore -> DB: UPDATE dbo.UserAccount\nSET Username = @UserName, ... UserStore --> UserMgr: IdentityResult UserMgr --> UpdateUsernameHandler: IdentityResult deactivate UserMgr alt !result.Succeeded UpdateUsernameHandler -> Mediator: throw ConflictException\n(DuplicateUserName code ->\n"Username already exists") Mediator -> API: propagate API -> User: 409 Conflict else result.Succeeded UpdateUsernameHandler --> Mediator: UpdateUsernamePayload(\n user.Id, user.UserName) deactivate UpdateUsernameHandler Mediator --> API: UpdateUsernamePayload deactivate Mediator API -> User: 200 OK\n{message: "Username updated successfully.",\npayload: {...}} end end end deactivate API @enduml