- Featured order: Faro (100), Automations (90), WordPress (80),
Cloudflare Zone Ops (70), GPU Monitor (60). Scores set in each bundled
extension's manifest (both copies); Faro's lives in the registry index.
- Add illustrated covers for Kubernetes and WordPress (extension-icons +
resolver rules) so they stop falling back to generic category glyphs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add Faro illustrated cover (extension-icons/faro.png) + resolver rule so
serverkit-faro shows a 3D lighthouse instead of a flat glyph.
- Mark Cloudflare Zone Ops featured (score 95) in both plugin.json copies.
- Add a wordpress.detail.panel PluginSlot so the Faro (and future WP)
extensions can render on WordPress site pages.
- Sync the registry offline fallback with the Faro v1.0.1 entry (featured).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move serverkit-gpu from CONVERTED_BUILTIN_SLUGS into GATED_BUILTIN_SLUGS behind
a _gpu_present() predicate (shutil.which('nvidia-smi')), mirroring the email
gate: fresh installs stay marketplace-only, upgraded panels without a GPU no
longer get it, upgraded panels with a GPU keep it (D3 continuity). Rewrite the
12 builtin + baked extension descriptions that used em dashes into plain
sentences, keeping every pair in sync. New test_extension_manifests.py walks
both manifest trees to assert no em/en dashes and per-slug description parity.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Moves the Cloudflare per-zone control panel (zone settings, cache purge, WAF,
Workers, Tunnels, R2/KV/D1 storage) out of core into the bundled, default-installed
`serverkit-cloudflare-ops` extension (#36). Much cleaner than WordPress:
- Backend: only 2 files move — `api/cloudflare.py` + `cloudflare_service.py` →
`builtin-extensions/serverkit-cloudflare-ops/backend/` (blueprint keeps
/api/v1/cloudflare, D9; the one intra-extension import made relative). ZERO core
callers (the service's only importer was its own blueprint), so no bridge
accessors are needed for core — `cloudflare_ops_bridge.py` exists only so the
moved test can reach the service by a dash-safe importlib path.
- No duplicate Cloudflare client (the hard constraint): the moved CloudflareService
still borrows the single core CloudflareClient via DNSZoneService._resolve_credential.
The whole DNS layer (dns/cloudflare.py, dns_zone_service, dns_provider_service,
DNSProviderConfig) and the CloudflareWorker/CloudflareTunnel models (FK into
dns_provider_configs) STAY core.
- Flagship (default-installed, uninstallable): added to FLAGSHIP_SLUGS — zero nav
footprint, and the core Domains "Open in Cloudflare" button depends on the route.
- Frontend: a single plain route `cloudflare/zones/:zoneId` contributed via the
manifest + a re-export shim; the page/panels/api-client/SCSS stay in core
(Pattern A). Core App.jsx import + route removed.
- Retired the core blueprint registration; the plugin status guard is the gate.
Verified: 80 tests green (new tests/test_cloudflare_extraction.py + the moved
test_cloudflare_zone_settings.py + the 4 DNS-layer tests that stay core and still
exercise the shared client); npm run lint + build clean; the backend serves the
`cloudflare/zones/:zoneId` route contribution from the seeded flagship row.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>