Probe with host-key pinning, tar-stream the docroot, dump the DB
through the tunnel and rebuild via the existing import/URL-swap path;
3-step UI at /wordpress/ssh-import. Password auth needs sshpass;
secrets never hit argv or logs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PluginLoader's legacy auto-render (any plugin index default export
renders globally) only excluded plugins that declared a WIDGET
contribution. The WordPress and Cloudflare-ops builtins declare routes
+ nav but no widgets, and their index modules had surplus default
exports — so their PAGES mounted globally on every route: the CF zone
page ran with zoneId=undefined (zones/undefined/settings 404s), the
WordPress sub-router swallowed the current location as a site id
(/domains → sites/domains 404s), and visited pages stacked into one
view ('5 pages in one'). Reproduced live via Playwright.
- legacy auto-render now skips any plugin declaring ANY contribution
(routes, nav, tabs, widgets, palette, layouts, ai) — those own their
rendering; serverkit-gui keeps working via its declared widget
- surplus default exports removed from both builtins (synced copies +
builtin-extensions sources) with do-not-re-add comments; routes
resolve named exports
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Completes #38: the WordPress frontend now belongs to the extension too, not just
the backend. The tab-group constraint (contributed routes are flat — there's no
way to contribute a shared TabGroupLayout parent inside the dashboard) is solved
by contributing a SINGLE splat route `wordpress/*` whose component
(WordPressExtension) self-renders the whole WordPress sub-router — reproducing the
exact structure core App.jsx used to own:
- TabGroupLayout + WORDPRESS_TABS over the 3 list pages (sites / plugin library /
pipelines),
- full-bleed site + pipeline detail routes as siblings,
- the legacy /wordpress/projects → /wordpress/pipelines deprecation redirects.
The 5 page components stay in core pages/ and are re-used (Pattern A, same as
serverkit-git/email/workflows); only the routing + nav/palette/title ownership
moves into the manifest.
- builtin-extensions/serverkit-wordpress/frontend/index.jsx (source) → synced to
frontend/src/plugins/serverkit-wordpress/ (pre-bundled, D5) via
scripts/sync-builtin-frontends.mjs (drift check green).
- plugin.json contributions: nav (WordPress), routes ([{path:"wordpress/*",
component:"WordPressExtension"}]), page_titles, command_palette.
- Core App.jsx: removed the WordPress imports, the TabGroupLayout WORDPRESS_TABS
route block, the detail routes, LegacyWpPipelineRedirect, and the now-unused
ModuleRoute + WORDPRESS_TABS imports (kept the dynamic /wordpress/ title
fallbacks). Removed the sidebar nav item and the two command-palette entries.
WordPress now disappears cleanly (nav+routes+API) when the extension is
uninstalled.
Verified: npm run lint (0 errors) + npm run build clean; the screenshots skill
renders /wordpress/42 correctly (visually confirmed — full detail page, Overview
tab, sidebar item active); backend flagship still seeds/loads (has_frontend now
true) with tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The largest single move in the plan (#38). The entire WordPress backend leaves
core for the bundled, default-installed serverkit-wordpress extension (D4).
Moved (12 files → builtin-extensions/serverkit-wordpress/backend/, intra-extension
imports made relative, core imports stay absolute):
api/wordpress.py, api/wordpress_sites.py, api/environment_pipeline.py,
wordpress_service.py (2676 lines), git_wordpress_service, wordpress_env_service,
wordpress_plugin_library_service, wp_analytics/reports/security/update/vulnerability.
Wiring:
- Blueprints keep /api/v1/wordpress, /wordpress/projects and the /wordpress/pipelines
alias (D9) via new manifest `extra_blueprints` support (3 blueprints / 4 mounts).
- Flagship (D4): seeded active on every panel (fresh + upgrade), uninstallable,
never deletes tracked builtin/pre-bundled files; the `wordpress` module toggle is
retired (MODULES now empty) — the plugin status guard is the gate.
- Loadability: the dashed package app.plugins.serverkit-wordpress is registered
in-place via spec_from_file_location (no copy) — uniform across prod/dev/test.
- The 11 WP test files re-pointed through app.services.wordpress_bridge; the 6 lazy
core callers were re-pointed in the prior commit.
- _regenerate_frontend_manifest() is a no-op under testing so the flagship boot
seed can't clobber the checked-in plugins-manifest.json.
Deviations (documented, matching the Email precedent):
- WordPress *models* stay core — status_page/environment_activity/promotion_job hold
FKs into wordpress_sites, so relocation would be a breaking data migration.
- Event catalog + Fail2ban WP filter stay core as two-speed items (extension calls
them via core APIs); inverting adds risk without blocking the move.
- Frontend UI stays core this session (it lives in a TabGroupLayout — the tab-grouped
conversion Phase 1 deliberately deferred); the extension is backend-only, so there
is no route duplication. Frontend contribution is the scoped follow-up.
Verified: clean collection across all 1223 tests; 199 passed / 2 skipped / 0 failed
across the WP + plugin/extension + module + backup + core-caller parity set, incl.
the new tests/test_wordpress_extraction.py proving the move.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>