Remove client-side Blazor script and normalize session IP display #20

Merged
hannah-vernon merged 1 commit from fix/admin-static-ssr-banner into dev 2026-08-25 23:00:03 -05:00

What does this PR do?

Two fixes from Hannah''s first live session on the admin UI (found within minutes of go-live, which is exactly what first live sessions are for):

  1. Removes the client-side Blazor machinery. The template''s blazor.web.js script tag and ReconnectModal component shipped in App.razor even though every admin page is static SSR with plain HTML form posts and Program.cs registers no interactive render mode. The script''s startup failure toggled Blazor''s "An unhandled error has occurred - Reload" banner on the anonymous pages (login, change-password) while the flows themselves worked fine server-side. The app now ships zero client-side script; the orphaned reconnect modal files and the never-triggerable error banner div are deleted. Bonus hardening: with no inline import map, the CSP''s script-src drops 'unsafe-inline' and is now just 'self'.
  2. Normalizes session IP addresses. Kestrel''s dual-stack socket reports IPv4 clients as IPv4-mapped IPv6 (::ffff:192.168.0.x), and the session row stored that raw form, which the /account active-sessions list displayed verbatim. Addresses are normalized to their IPv4 form at session creation and in the rate-limiter partition key. IP-binding comparisons already normalized both sides, so no behavioral change - this is stored-data and display honesty.

How was this tested?

  • dotnet build - 0 errors, 0 warnings
  • dotnet test - 301 passed, 9 skipped (live-PostgreSQL integration tests)
  • Live re-verification on the VM post-merge: banner gone on /login and /login/2fa, session list shows IPv4 addresses

Checklist

  • I have read the Contributing Guide
  • Changes are focused - one logical change per PR
  • Documentation updated (README.md / DECISIONS.md / TODO.md / AGENT-README.md, if applicable - none needed)
  • New dependencies are MIT/Apache-2.0/BSD, security-vetted, and recorded in THIRD-PARTY-NOTICES.md (none added)
  • No secrets, credentials, or real infrastructure identifiers in the diff
  • No commented-out code or debug leftovers
## What does this PR do? Two fixes from Hannah''s first live session on the admin UI (found within minutes of go-live, which is exactly what first live sessions are for): 1. **Removes the client-side Blazor machinery.** The template''s `blazor.web.js` script tag and `ReconnectModal` component shipped in `App.razor` even though every admin page is static SSR with plain HTML form posts and Program.cs registers no interactive render mode. The script''s startup failure toggled Blazor''s "An unhandled error has occurred - Reload" banner on the anonymous pages (login, change-password) while the flows themselves worked fine server-side. The app now ships **zero client-side script**; the orphaned reconnect modal files and the never-triggerable error banner div are deleted. Bonus hardening: with no inline import map, the CSP''s `script-src` drops `'unsafe-inline'` and is now just `'self'`. 2. **Normalizes session IP addresses.** Kestrel''s dual-stack socket reports IPv4 clients as IPv4-mapped IPv6 (`::ffff:192.168.0.x`), and the session row stored that raw form, which the /account active-sessions list displayed verbatim. Addresses are normalized to their IPv4 form at session creation and in the rate-limiter partition key. IP-binding comparisons already normalized both sides, so no behavioral change - this is stored-data and display honesty. ## How was this tested? - [x] `dotnet build` - 0 errors, 0 warnings - [x] `dotnet test` - 301 passed, 9 skipped (live-PostgreSQL integration tests) - [ ] Live re-verification on the VM post-merge: banner gone on /login and /login/2fa, session list shows IPv4 addresses ## Checklist - [x] I have read the [Contributing Guide](../CONTRIBUTING.md) - [x] Changes are focused - one logical change per PR - [x] Documentation updated (README.md / DECISIONS.md / TODO.md / AGENT-README.md, if applicable - none needed) - [x] New dependencies are MIT/Apache-2.0/BSD, security-vetted, and recorded in THIRD-PARTY-NOTICES.md (none added) - [x] No secrets, credentials, or real infrastructure identifiers in the diff - [x] No commented-out code or debug leftovers
Two fixes from the first live use of the admin UI:

- The template's blazor.web.js and ReconnectModal shipped even though
  every admin page is static SSR with plain HTML form posts and no
  interactive render mode is registered.  The script's startup failure
  toggled the 'An unhandled error has occurred' banner on anonymous
  pages (login, change-password) despite the flows working.  The app
  now ships no client-side script at all, which also lets the CSP
  drop 'unsafe-inline' from script-src (the inline import map was the
  only reason it existed).
- Session rows stored the dual-stack socket's IPv4-mapped IPv6 form
  (::ffff:192.168.0.x), which the /account session list displayed
  verbatim.  Addresses are now normalized to their IPv4 form at
  session creation and in the rate-limiter partition key.  Binding
  comparisons already normalized both sides, so behavior is unchanged;
  this is display and stored-data honesty.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
hannah-vernon force-pushed fix/admin-static-ssr-banner from 1721aeb15b to 8a9ad5ad4b 2026-08-25 22:59:45 -05:00 Compare
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
hannah-vernon/viegard-sentinel!20
No description provided.