Skip to content

fix: ADC Local Test Run 3 defects (transport faults, login protection outage, register alert, role PUT, client IP) - #492

Merged
ivanball merged 1 commit into
mainfrom
fix/test-run-3-defects
Oct 4, 2026
Merged

ivanball merged 1 commit into
mainfrom
fix/test-run-3-defects

Conversation

@ivanball

@ivanball ivanball commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Fixes the MMCA.Common defects found by ADC Local Test Run 3 (221 manual cases run locally with up to six concurrent browser users) and confirmed in source by an independent reviewer.

Defect Seen as Fix
Polly TimeoutRejectedException / BrokenCircuitException escape HttpResultExecutor ADC X-07, U-35: a stopped or hung backend turns signed-in and signed-out session lists into a full-page 500 IsTransportFault also matches ExecutionRejectedException, so the page gets a failed Result and shows its error with Retry
Login protection rethrows cache failures POST /Auth/login answers 500 while Redis is down LoginProtectionService fails open with a Warning log on every check, increment and reset; caller cancellation still propagates. Decision recorded in ADR-029 (Website PR, revision 2026-10-03)
Duplicate-email alert renders the live field ADC U-13: editing the email after a rejection re-prints "already registered" for an unchecked address The alert names the rejected address and the first edit dismisses it
Unaccented Spanish "correo electronico" in the user admin list UserAdminListResources.es.resx accented
PUT permissions on an unknown role succeeds ADC O-54: PUT /Admin/Roles/{typo}/permissions 200 while GET is 404 SetStoredPermissionsAsync answers RoleNotFound and stores nothing
Server-side API calls carry no client IP Registrations from the Blazor Server path all count against the UI host's address BrowserForwardedForHandler on the "APIClient" pipeline stamps X-Forwarded-For with the browser IP (same source as CookieSessionRefresher.BrowserOrigin); the WASM path is unchanged

Public API: LoginProtectionService gains a trailing optional ILogger<LoginProtectionService>? constructor parameter (recompile only).

Verification (local): dotnet build MMCA.Common.slnx -c Release 0 warnings / 0 errors; test exes UI 1229, Infrastructure 1723, API 866, UI.Web 205, Architecture 317, all 0 failed.

Note for reviewers: the client-IP handler reads IHttpContextAccessor per request, like the refresher. Prerender calls get the page request; interactive circuit calls rely on the accessor exposing the circuit's connection. If it does not, those calls send no header (no regression). The post-deploy ADC check confirms which.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sDGvYdTD88ZjjD7if2SMW

- HttpResultExecutor treats Polly ExecutionRejectedException (timeout,
  open circuit) as a transport fault, so a down or hung backend becomes a
  failed Result instead of a prerender 500 (ADC X-07, U-35).
- LoginProtectionService fails open with a Warning log when the cache is
  unavailable instead of answering 500 on login and register; caller
  cancellation still propagates (ADR-029 revision 2026-10-03).
- Register: the duplicate-email alert names the rejected address and is
  dismissed by the first edit of the field (ADC U-13).
- UserAdminList Spanish strings accented.
- SetStoredPermissionsAsync answers RoleNotFound for a role outside the
  role universe and stores nothing, matching GetRoleAsync (ADC O-54).
- AddCommonServerTokenStorage stamps X-Forwarded-For with the browser IP on
  server-side APIClient calls, so Identity's per-IP registration limit keys
  on the browser rather than the UI host (WASM path unchanged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sDGvYdTD88ZjjD7if2SMW
@ivanball
ivanball merged commit e7dad52 into main Oct 4, 2026
16 checks passed
@ivanball
ivanball deleted the fix/test-run-3-defects branch October 4, 2026 00:23
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.

1 participant