` *after* the
`in_admin_header` hook fires (confirmed directly in core's
`admin-header.php`), but `ScreenHijack.php` started its output buffer
*on* `in_admin_header` — so those wrapper divs' opening tags, and later
their closing tags (printed before `admin_footer` fires), both ended up
inside the buffer and got discarded along with the native content they
were meant to replace. The mount div ended up a level too high in the
DOM (a direct child of `#wpcontent`), which broke `windowChrome.js`'s
`#wpbody-content`-based traffic-light insertion and the shell's card
framing CSS. Fixed by having `ScreenHijack.php` re-print the `#wpbody`/
`#wpbody-content` wrapper divs itself around the mount point, so the DOM
matches what WordPress would have produced. Verified live on Posts,
Media, Users, and Profile.
## [2.13.0] - 2026-07-05
### Added
- Sixth and final phase of the "full admin takeover" initiative: the block
editor (`post.php`/`post-new.php`). Deliberately a reskin, not a rebuild
— Gutenberg stays completely native, extending the framing
`windowChrome.js`/`shell-frame.css` already had working (traffic-light
dots overlaid on the editor). Added a "← Posts"/"← Pages" breadcrumb next
to the dots, resolved from the `post-type-{slug}` body class WP core
already adds to every post edit screen (needed since Posts/Pages moved
off a fixed `admin.php?page=...` URL onto their native URLs earlier this
phase, so there's no single URL to hardcode).
- Caught and fixed a real bug while testing: the Site Editor
(`site-editor.php`) shares the same `block-editor-page` body class the
breadcrumb logic keyed off, but has no `post-type-*` class (it edits
templates, not a post) — the original version defaulted to guessing
"Posts" there, which was wrong. Now returns no breadcrumb at all when
no `post-type-*` class is present, verified live on both the post
editor (crumb shows, correct link) and the Site Editor (no crumb,
nested-skeleton framing unaffected).
- This is the last screen in the "full admin takeover" initiative's
original 9-item build order. All 9 phases are now shipped.
## [2.12.0] - 2026-07-05
### Added
- Fifth phase of the "full admin takeover" initiative: Profile
(`profile.php`), reskinning WordPress's own fields (name, contact info,
bio) via core's `/wp/v2/users/me` REST route, plus a small new
`ProfileData.php` route for password changes (core deliberately excludes
password from its own REST schema). Free, gated by `modern_users`.
- Deliberately does not attempt to host third-party plugin fields (2FA
setup, WooCommerce customer fields, etc., added via the
`show_user_profile`/`personal_options` hooks) — a Vue reskin has no
safe way to render another plugin's raw HTML/JS. Instead, the hijack
checks `has_action('show_user_profile')`/`has_action('personal_options')`
at hijack time and falls through to the real native screen whenever
either has a callback registered, rather than silently hiding those
plugins' fields. Verified live both ways: installed a test mu-plugin
hooking `show_user_profile` and confirmed the native screen renders
instead of the reskin; removed it and confirmed the reskin returns.
- Password changes re-issue the auth cookie immediately after
`wp_set_password()` (which invalidates the current session, since it's
derived in part from the password hash) — same as core's own
user-edit.php does when you change your own password.
## [2.11.0] - 2026-07-05
### Added
- Fourth phase of the "full admin takeover" initiative: the Appearance
batch. Nav Menus (`nav-menus.php`) and Widgets (`widgets.php`) are real,
purpose-built replacements — not wired into the existing Menu Creator,
which manages Aurora's own admin sidebar and turned out to be an unrelated
feature despite the similar name. Themes (`themes.php`) is a real
list/activate/delete replacement (`ThemesData.php` + `Themes.vue`). Theme
Editor (`theme-editor.php`) redirects to the existing File Manager instead
of getting a second in-browser file editor — building one would duplicate
File Manager's exact RCE risk surface for no benefit. Tools, Import/Export,
and Site Health are deliberately left un-hijacked; Shell's existing
native-page framing already covers them and a full rebuild has no real
value-add over core's own screens.
- Widgets is deliberately simplified to reordering/moving/deactivating
existing widget instances between sidebars — adding a brand-new
instance of an arbitrary widget type still uses WordPress's own
block-based widgets screen (each widget type owns its own default
settings and form; genericizing that is a full editor's worth of scope
on its own, same reasoning as not rebuilding the block editor).
- Nav Menus supports the common paths: create/delete menus, add
pages/posts/categories/custom links, reorder and indent/outdent
(sub-menu) items, assign menus to theme locations.
- All three (plus Native Settings, previously shipped) are gated by the
`full_admin_takeover` master toggle and the `"admin-takeover"` paid
feature; every new REST controller checks the license directly in its
own `permission_callback`, not just at the page level.
- Fixed a real frontend bug caught while testing these against a 403 (no
license): `Themes.vue`, `Widgets.vue`, and `NavMenus.vue`'s fetch calls
didn't check `res.ok` before treating the response body as the expected
data shape — a REST error object (`{code, message, data}`) got rendered
as if it were the actual list, producing bogus placeholder rows instead
of a clear error message. All three now surface the real error.
- Verified live: Themes' activate/list/screenshot rendering confirmed
working end-to-end (switched between all 3 installed themes); Nav Menus
and Widgets' REST layer verified directly (create/add-item/list/delete
round trip, real sidebar data) — the pages themselves couldn't be
rendered in this dev environment since none of the 3 installed themes
register classic nav-menu/widget support (all are block/FSE themes,
which core itself refuses these screens for too — not a defect in the
hijack).
## [2.10.0] - 2026-07-05
### Added
- Third phase of the "full admin takeover" initiative: Media Upload
(`media-new.php`) and Add New User (`user-new.php`) are now hijacked in
place. Both are Vue-only — no new PHP REST controllers — talking directly
to core's own `/wp/v2/media` and `/wp/v2/users` REST routes, which already
cover file upload and user creation. Free, gated by the same
`modern_media`/`modern_users` toggles as their already-free list-view
companions (no reason to paywall mid-workflow between "browse" and "add").
Verified live end-to-end: created a real user and confirmed it appears in
the Users list.
## [2.9.0] - 2026-07-05
### Added
- Second phase of the "full admin takeover" initiative: the 5 native
Settings screens (General, Writing, Reading, Discussion, Permalinks) are
now hijacked in place (`NativeSettingsPages.php`), sharing one generic
Vue page (`NativeSettings.vue`) driven by a per-screen field schema.
Most fields read/write through core's own `/wp/v2/settings` REST route;
Permalinks has no core REST route for rewrite rules, so it gets its own
small `PermalinksData.php` controller instead (calls
`$wp_rewrite->set_permalink_structure()` + `flush_rules()`, same as core's
own settings page does).
- New master toggle, Settings > Admin Takeover > "Full admin takeover"
(default **off** — these new areas cover more ground and carry more risk
than the already-migrated Posts/Pages/Media/Users/Comments, so opt-in
rather than on by default), plus a new `"admin-takeover"` paid feature key.
Every new REST controller in this phase checks
`License::is_feature_available("admin-takeover")` directly in its own
`permission_callback`, not just at the page level — the same defense the
File Manager REST controller already has, verified live by confirming a
direct REST call still 403s with the setting on but no license.
- `SettingsField.vue` (shared by the main Settings page and the new native
Settings screens) gained two small additions: `readonly` support on text
fields (Site Address shouldn't be editable inline) and a `select` field
type (a plain dropdown, distinct from the existing multiselect checkbox
list) — both minimal, generically useful additions, not one-offs.
## [2.8.0] - 2026-07-05
### Added
- First phase of the "full admin takeover" initiative: Posts, Pages, Media
Library, Users, and Comments no longer redirect to a separate
`admin.php?page=...` URL — they now hijack their native screens in place
(`ScreenHijack.php`, registered via `HijackedNativePages.php`), the same
approach the original uixpress reference plugin used. WordPress's
`load-{page}.php` hook fires before the native screen prints anything, so
Aurora buffers and discards the native output and mounts its own Vue page
in its place — the URL never changes, so there's no separate slug that can
fall out of sync with a plugin's own redirect, a bookmark, or any other
direct visit. This is exactly the bug class already hit and fixed once for
Plugins; the other five pages are now structurally immune to it. Plugins
itself stays on the redirect mechanism — `plugins.php` prints output in a
way that can't be cleanly buffered, confirmed by the reference plugin's own
abandoned attempt at hijacking it.
- Existing REST controllers and Vue pages for all five are unchanged — only
the mounting mechanism moved.
## [2.7.2] - 2026-07-05
### Fixed
- Installing/activating a plugin dropped back to the native WordPress
Plugins page instead of staying in Aurora's UI, until the sidebar's
"Plugins" link was clicked again. Unlike Posts/Pages/Media/Users/
Comments, Plugins only ever had its sidebar *link* rewritten
(`MenuSerializer.php`) — there was no `redirect_native_pages()` case
for direct visits to `plugins.php`, which is exactly what WordPress's
own post-activate/post-install redirect does
(`wp_redirect(self_admin_url('plugins.php?activate=true'))`, no
`?page=` param). Added the missing case, matching the pattern already
used for the other four pages.
## [2.7.1] - 2026-07-05
### Fixed
- Native form fields (text inputs, textareas, selects) on several
classic/non-block-editor screens — most visibly the title field on the
Edit Media screen, but the same fix applies wherever it occurred — were
showing stark white, breaking the dark theme. Root cause: some native
WP screens style specific fields via a 2-ID selector (e.g. core's
`#titlediv #title { background: #fff }`), which beats our existing
rule's single `#wpbody-content` id no matter how many classes are
stacked on it — the exact same CSS-specificity trap as an earlier
block-editor background bug. Added `!important` to the form-field rule
block, since there's no legitimate case where a native admin form field
should stay white.
## [2.7.0] - 2026-07-05
### Added
- New File Manager (`aurora-admin-file-manager`), browsing/editing the
WordPress install's own files — built fresh (not embedding elFinder),
in the spirit of the "WP File Manager" plugin already on this site
(same root, same `manage_options`-only gate). Create/upload/download/
rename/delete files and folders, plus a plain-text editor for
code/config files. A **Pro feature** — the riskiest surface in the
whole plugin (arbitrary read/write access to the site's own PHP files),
so it's gated the same way as Database Explorer.
- Every path a client sends is resolved to a real, `ABSPATH`-contained
path via `realpath()` before any filesystem operation — containment
is checked against the resolved path, not string-matched against the
raw input, so symlink tricks and encoded traversal can't slip past.
- Uploads/new files/renames all reject a blocklist of server-executable
extensions (`.php`, `.phtml`, `.cgi`, `.sh`, etc.) — the single most
important control here, since uploading a webshell is the whole ballgame.
- Deliberately not built: zip/unzip (zip-slip extraction vulnerability),
chmod/permissions editing, and cross-directory move/copy — each is a
meaningfully larger, riskier scope than a first pass warrants.
### Fixed
- File Manager's REST endpoints now also check
`License::is_feature_available('file-manager')`, not just
`manage_options` — found while wiring it up that the page-level lock
alone doesn't stop a direct REST call from bypassing it entirely.
**The same gap exists in Database Explorer, Role Editor, and Activity
Log's REST controllers and is not yet fixed** — flagged as a follow-up.
## [2.6.0] - 2026-07-05
### Added
- Real replacement pages for Pages, Media Library, and Users — the
remaining native admin screens that were only dark-themed skinning,
now built the same way as Posts/Comments/Plugins (own REST controller,
own Vue page, native screen redirected away):
- **Pages** (`PagesData.php` + `Pages.vue`): same as Posts, but shows
the parent page instead of categories. `edit.php?post_type=page`
redirects; other post types are untouched.
- **Media Library** (`MediaData.php` + `Media.vue`): a thumbnail grid
(not a rebuilt drag-drop uploader) with type filters (Images/Audio/
Video/Documents/Unattached), search, and delete. `upload.php`
(both grid and list mode) redirects; `media-new.php` (the actual
upload screen) is untouched, same reasoning as leaving the block
editor alone for Posts/Pages.
- **Users** (`UsersData.php` + `Users.vue`): filterable by role, with
edit/delete actions. Deleting a user always reassigns their content
to whoever performs the deletion, rather than exposing WP core's
reassign-or-delete-everything choice as a one-click REST action —
deliberately simplified to avoid a surprising, highly destructive
default. `users.php` redirects; `user-new.php` (account creation)
is untouched.
- All four gated by their own Settings toggle (`modern_pages`,
`modern_media`, `modern_users` — `modern_posts` already existed),
each defaulting to on.
## [2.5.0] - 2026-07-05
### Added
- Real replacement Posts management page (`aurora-admin-posts`), the same
kind of full custom page as Comments/Plugins rather than dark-themed
skinning over the native `edit.php` list table. New `PostsData.php` REST
controller (list with status/search filters, trash, restore, permanent
delete) and a new Vue page matching the Comments layout (status filter
pills, search, table with title/author/categories/comments/date/status,
inline row actions, pagination). The native Posts screen (`edit.php`,
default post type only — Pages and other post types are untouched)
redirects to it, gated by Settings > Posts' restored "Modern posts
table" toggle (removed a few commits ago when it had no implementation
behind it — now it does).
### Fixed
- The `modern_plugins`/`modern_comments` settings toggles now default to
visually "on" in the Settings UI to match their actual PHP default
(previously they defaulted true server-side but showed off in the UI
until explicitly saved) — same fix applied to the new `modern_posts`.
## [2.4.2] - 2026-07-04
### Fixed
- Admin Notices only ever showed on the Aurora Dashboard — everywhere
else, `admin_notices` fired normally, but on the Dashboard specifically
the notice was invisible: `DashboardTakeover` hides `#wpbody` entirely
there (to hide the *native* dashboard, not our own), and that's exactly
where WordPress prints `admin_notices` output. Notices now render
directly inside the Aurora dashboard frame instead on that one page.
Along the way, also worked around a separate WordPress core behavior
(`common.js` unconditionally relocates every `.notice` element to right
after the page's `
`) using core's own documented `below-h2` opt-out
class, since without it the notice would've just been silently moved
back into the hidden `#wpbody` by that script regardless of where it
was placed server-side.
## [2.4.1] - 2026-07-04
### Fixed
- Dashboard scrolling was broken — content below the first ~1500px
(Server Health, Media Analytics, etc.) was completely unreachable.
`.aurora-dashboard-frame` never got the height cap + internal scroll
treatment `#wpbody-content` got in an earlier fix; combined with
`html`/`body` being locked to `overflow: hidden` (to fix a phantom
scrollbar on a different page), there was no scroll mechanism left at
all for the dashboard specifically. Mirrored the same
max-height/overflow-y treatment onto `.aurora-dashboard-frame`.
## [2.4.0] - 2026-07-04
### Added
- Settings > Menu's "Menu search" toggle now actually does something —
previously had no implementation at all. Shows a real search box at the
top of the sidebar that filters both the WP-native menu list and the
Aurora nav section by title, auto-expanding every section with a match.
### Fixed
- Settings > Dashboard's "Custom dashboard" toggle now actually gates the
dashboard takeover — previously the Aurora dashboard always replaced the
native one regardless of this setting, with no way to turn it back off.
- Settings > Plugins' "Modern plugins page" and Settings > Comments'
"Modern comments page" toggles now actually gate their respective
takeovers/redirects the same way — previously both ran unconditionally
regardless of these settings.
### Removed
- Settings > Posts' "Modern posts table" and Settings > Users' "Modern
users page" toggles — both described a custom management interface that
was never built. Shipping a checkbox with nothing behind it is worse
than not having the checkbox; removed rather than left as dead UI. Their
categories are removed too, since they had no other fields.
## [2.3.1] - 2026-07-04
### Fixed
- Sidebar accordion now treats the "Aurora" branded nav section as part of
the same single-open accordion as the WP-native menu list, instead of
being the one exception that stayed open regardless of what else was
expanded. Expanding any native section now collapses Aurora too, and
vice versa.
## [2.3.0] - 2026-07-04
### Added
- Settings > Media's "Allow SVG uploads" toggle now actually does
something — previously existed in the UI with no implementation behind
it, so every SVG upload was rejected. Fixes both of WordPress's default
blocks (the `upload_mimes` allowlist and the real-mime sniff that nulls
out the file type for SVGs specifically), plus a PHP warning
(`wp_get_missing_image_subsizes()` reading undefined `width`/`height`
metadata keys that SVGs never had) that could otherwise corrupt the
upload response on environments with warnings displayed inline. Also
does basic sanitization on upload (strips `