Feature: A logged-in, unverified user cancels their pending registration As the maintainer of RenewCMS I want a logged-in user who has not yet verified their account to be able to delete that account and clear their session in one call, while a user who is already verified cannot use this route to delete their own account, and a token that carries no usable user_id is answered with 401 instead of a panic So that someone who registered by mistake, or changed their mind before verifying, can free their username and email immediately (features/unverified_users_and_reregistration.feature), without exposing a general self-delete for verified accounts Background: Given this slice adds DELETE /v1/auth/register, mounted in api/router.go inside the same protected group NewAuthRouter already applies to POST /v1/auth/verify: jwtauth.Verifier then jwtauth.Authenticator, so a request with no jwt cookie, an expired jwt, or a jwt with a bad signature never reaches the handler and is answered 401 by jwtauth.Authenticator itself And the handler extracts user_id from the already-verified token's claims using the same safe pattern auth.Handler.Verify already established (features/account_verification.feature): 401 with apperr.UnauthorizedErrorMessage whenever the "user_id" claim is missing, is not a number, or does not match any user in the repository, never a panic and never trusting the raw claim value And a new use case, CancelRegistrationUseCase (internal/infrastructure/useCases/CancelRegistration.go), is injected into auth.Handler as CancelRegistrationUseCase; it depends only on user.Repository and exposes CancelRegistration(userId uint32) error And CancelRegistrationUseCase.CancelRegistration loads the user by id, returns the existing sentinel user.ErrUserNotFound when no such user exists, refuses with a new sentinel user.ErrAlreadyVerified when the loaded user's IsVerified is already true, and otherwise calls user.Repository.Delete(userId), whose GORM implementation removes the row entirely rather than soft-deleting it (features/unverified_users_and_reregistration.feature), so the same username and email are immediately free for a new registration And the handler maps user.ErrUserNotFound to 401 with apperr.UnauthorizedErrorMessage, the same status and body Verify already uses for an unresolvable user_id, and maps user.ErrAlreadyVerified to 403 with a new apperr.AlreadyVerifiedErrorMessage constant And on success the handler clears the "jwt" cookie exactly the way auth.Handler.Logout already does (Max-Age -1, empty value, Path "/") and responds 200 with {"message": "..."} And on any error path the handler returns before touching the "jwt" cookie, so an unresolved or already-verified request leaves the caller's existing session untouched Scenario: An unverified user cancels their pending registration Given a user repository containing user id 7, username "alice", email "alice@example.com", is_verified false And a valid jwt cookie for user id 7 When the client sends DELETE /v1/auth/register with that cookie Then the response status is 200 And the response body is {"message": "..."} And the response clears the "jwt" cookie And the user repository no longer contains user id 7; Get(7) returns user.ErrUserNotFound Scenario: Cancelling frees the username and email for a new registration Given a user repository containing user id 7, username "alice", email "alice@example.com", is_verified false And a valid jwt cookie for user id 7 When the client sends DELETE /v1/auth/register with that cookie Then the response status is 200 When the client sends POST /v1/auth/register with username "alice", password "hunter2example12", email "alice@example.com" Then the response status is 200 And a jwt cookie is set And the newly created user's id is different from 7 Scenario: An already-verified user cannot cancel their account this way Given a user repository containing user id 7, username "alice", email "alice@example.com", is_verified true And a valid jwt cookie for user id 7 When the client sends DELETE /v1/auth/register with that cookie Then the response status is 403 And the response body is the new apperr.AlreadyVerifiedErrorMessage text And the response does not clear the "jwt" cookie And the user repository's record for id 7 is unchanged: is_verified true, the row still exists Scenario Outline: A token without a valid user_id returns 401 instead of crashing Given a user repository containing user id 7, username "alice", is_verified false And When the client sends DELETE /v1/auth/register with that cookie Then the response status is 401 And the response body is the apperr.UnauthorizedErrorMessage text And the handler does not panic And the response does not clear the "jwt" cookie And the user repository's record for id 7 still exists Examples: | token description | | a validly signed jwt cookie whose claims carry no "user_id" key at all | | a validly signed jwt cookie whose "user_id" claim is the string "seven" | | a validly signed jwt cookie whose "user_id" claim is the number 999, which does not match any user | Scenario: A request with no jwt cookie never reaches the handler Given a user repository containing user id 7, username "alice", is_verified false And no jwt cookie is sent When the client sends DELETE /v1/auth/register without a cookie Then the response status is 401 And the user repository's record for id 7 still exists Scenario: The use case deletes an unverified user, independently of any handler Given a user.Repository fake containing user id 3, is_verified false And a CancelRegistrationUseCase built directly over that fake When CancelRegistration is called with userId 3 Then the call returns nil And the fake repository no longer contains user id 3 Scenario: The use case refuses to delete an already-verified user, independently of any handler Given a user.Repository fake containing user id 3, is_verified true And a CancelRegistrationUseCase built directly over that fake When CancelRegistration is called with userId 3 Then the call returns user.ErrAlreadyVerified, asserted with errors.Is And the fake repository still contains user id 3 Scenario: The use case reports an unknown user, independently of any handler Given a user.Repository fake containing no user with id 42 And a CancelRegistrationUseCase built directly over that fake When CancelRegistration is called with userId 42 Then the call returns user.ErrUserNotFound, asserted with errors.Is