dist/index.html was pointing at index-DTpNyCcP.js, a bundle left over from
mid-rebase: three consecutive admin-UI commits ("match the reserved-usernames
page layout to the NFT page", "self-contained reserve-username modal", "use
the standard dry-run/confirm flow") each conflicted on dist/index.html, and
resolving each by keeping the already-applied side discarded that commit's
own frontend rebuild. The result was a built bundle several commits stale
relative to the actual ServerSettingsPage.tsx source, which crashed on load
(Cannot read properties of null (reading 'reduce')) since it no longer
matched the current API shape.
Rebuilt via `npm run build` against current source and removed the orphaned
stale bundles.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Both reserve and unreserve go through ActionButton now (reason -> dry-run ->
confirm, journalled) like every other admin action. The reserve modal keeps
just the username field and hands off; it autofocuses and echoes @<name> live
so the field being filled is unambiguous.
The reserve modal delegated to a nested ActionButton, whose own flow modal
opened over it - the username field ended up behind it and the request preview
came through empty on confirm. Replace it with a modal that owns its username
and reason fields and posts the reserve/unreserve command directly. Render the
@ prefix as text, not an icon.
Move "Reserve username" into a modal opened from the page actions, and keep a
single search toolbar in the query panel, so the page matches Collectible
Usernames instead of stacking two toolbars with an unconstrained input.
The "*" wildcard was never in assignablePermissions, so an operator holding it
(the one the first-run wizard creates) showed every box unticked while having
every right, and there was no way to take it away. Its own row fixes both; the
grid is disabled while it is on, since normalisePermissions collapses "*" plus
anything back to "*".
That made guardManagerRemoval reachable from the UI for the first time, so it
now has an integration test covering the wildcard match and the enabled filter
in its SQL.