Skip to content

[wasm-posix-kernel] WordPress Playground Web Kandelo Beta - Proof of concept - #3957

Open
mho22 wants to merge 4 commits into
playground-web-experimental-posix-kernelfrom
playground-web-kandelo-beta
Open

mho22 wants to merge 4 commits into
playground-web-experimental-posix-kernelfrom
playground-web-kandelo-beta

Conversation

@mho22

@mho22 mho22 commented Jul 8, 2026 •

Copy link
Copy Markdown
Collaborator

Adds an experimental ?experimental=kandelo opt-in that runs WordPress Playground Web on the wasm-posix-kernel (kandelo) runtime instead of the classic PHP worker.

Built on top of #3635 (the kernel-mode web proof of concept); this PR is the opt-in wiring plus the deployment glue needed to actually serve it.

What it does

  • Client (@wp-playground/client) — assertLikelyCompatibleRemoteOrigin accepts /remote-posix-kernel.html alongside /remote.html, so kernel-mode sessions boot instead of throwing "Invalid remote URL".
  • Website — getRemoteUrl points the remote iframe at /remote-posix-kernel.html when ?experimental=kandelo is present. The kernel remote needs SharedArrayBuffer, which the browser only grants on cross-origin isolated pages, so when the page is not isolated we fall back to the classic runtime with a console warning instead of failing inside the worker. PlaygroundRoute.site preserves the experimental param when rewriting a stored-site URL (dropping it would silently switch a saved-site selection back to classic).
  • Deployment (serving) — /remote-posix-kernel.html is served cross-origin isolated (COOP same-origin, COEP require-corp, Document-Isolation-Policy). / and /index.html opt into isolation only under ?experimental=kandelo, because COOP same-origin otherwise breaks the GitHub OAuth popup for everyone else; those use COEP credentialless to keep cross-origin subresources loading without CORP headers. Dedicated worker scripts (the kernel remote's worker entries and the website's OPFS workers) are served with COEP require-corp: a dedicated worker script must carry a COEP header compatible with the document that spawns it, the dev server sets headers on every response, production did not — without this the workers fail to load. custom-redirects-lib.php covers the PHP deployment, .htaccess mirrors the headers for the static one.
  • Deployment (build & ship) — a build-experimental-posix-kernel nx target builds /remote-posix-kernel.html for production via a new build section in vite.posix-kernel.config.ts: its own dist/packages/playground/remote-posix-kernel output so the classic and kernel asset graphs never overwrite each other, plus the classic worker output rules so the shared service worker resolves to the same /sw.js (the artifact ships the classic-built copy). The build imports the kandelo host source from the kandelo/ submodule and the kernel binaries from @wp-playground/posix-kernel-builds. Regular website builds do not check out the submodule, so the target is not part of the website build graph: deploy-website.yml runs it before the website build, and build:wasm-wordpress-net packages the output only when present.

Tests

  • client/src/index.spec.ts — client accepts the kernel-mode remote entry pathname.
  • website/src/lib/config.spec.ts — runtime selection and the not-isolated fallback (+ warning).
  • website/src/lib/state/url/router.spec.ts — the experimental param is preserved across stored-site URL rewrites.
  • website-deployment/tests.php — the new cross-origin-isolation and worker-script header branches, plus the special-treatment routing that serves them via PHP.
  • website/playwright/e2e/posix-kernel/experimental-kandelo-param.spec.ts — e2e asserting the iframe entry URL swaps with the param.

The full chromium kernel e2e suite passes on this head: 117 passed, 10 skipped. Two dock-pane tests in website-ui.spec.ts timed out once under load and passed on 3 reruns each.

Verified end to end against a static server replaying the production header logic: the kandelo-opted artifact boots WordPress on first load and on the service-worker-controlled reload, and the classic mode stays non-isolated with cross-origin embeds loading.

Breaking changes

None.

@mho22
mho22 force-pushed the playground-web-kandelo-beta branch from 0b543c1 to 972da7a Compare July 14, 2026 15:17
mho22 added a commit that referenced this pull request Jul 14, 2026
…-module extensions

- Bump kandelo submodule f9c17d13 -> 9a7a6791 (current main tip). Main is
  still ABI v39, matching the immutable binaries-abi-v39 release assets.
- Replace `kandelo/scripts/fetch-binaries.sh` + the Rust toolchain CI step
  with `scripts/fetch-kandelo-binaries.mts`, which resolves binaries from
  the pinned index in `scripts/kandelo-pinned-binaries-index.toml`
  (immutable release assets, homedir cache, Windows-safe, no toolchain).
  `scripts/generate-kandelo-pinned-index.mts` regenerates the index.
- Wire the zip.so / curl.so / phar.so PHP side modules into both php-fpm
  (boot.ts argv + extensions mount at /usr/lib/php/extensions) and the
  `php` CLI spawns (php-api.ts PHP_EXTENSION_ARGS). Phar is built shared
  by kandelo; wp-cli.phar needs the Phar class.
- Kernel spawns run as uid 0, so export WP_CLI_ALLOW_ROOT=1 in the spawn
  env, and guard the STDIN/STDOUT/STDERR defines in the wp-cli blueprint
  step (the kernel CLI SAPI predefines them).
- Attach kandelo's TCP network backend (enableTcpNetwork) and point
  curl.cainfo at the kernel-installed CA bundle; add curl-https.spec.
- Raise the nginx-ready timeout to 180s and retry the wp-admin/install.php
  POST under load (loaded CI runners cold-start several kernels at once).

Ported down from the kandelo-beta branch (PR #3957) as the CLI-layer
slice of the stack rework.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mho22 added a commit that referenced this pull request Jul 14, 2026
…-module extensions

- Bump kandelo submodule f9c17d13 -> 9a7a6791 (current main tip). Main is
  still ABI v39, matching the immutable binaries-abi-v39 release assets.
- Replace `kandelo/scripts/fetch-binaries.sh` + the Rust toolchain CI step
  with `scripts/fetch-kandelo-binaries.mts`, which resolves binaries from
  the pinned index in `scripts/kandelo-pinned-binaries-index.toml`
  (immutable release assets, homedir cache, Windows-safe, no toolchain).
  `scripts/generate-kandelo-pinned-index.mts` regenerates the index.
- Wire the zip.so / curl.so / phar.so PHP side modules into both php-fpm
  (boot.ts argv + extensions mount at /usr/lib/php/extensions) and the
  `php` CLI spawns (php-api.ts PHP_EXTENSION_ARGS). Phar is built shared
  by kandelo; wp-cli.phar needs the Phar class.
- Kernel spawns run as uid 0, so export WP_CLI_ALLOW_ROOT=1 in the spawn
  env, and guard the STDIN/STDOUT/STDERR defines in the wp-cli blueprint
  step (the kernel CLI SAPI predefines them).
- Attach kandelo's TCP network backend (enableTcpNetwork) and point
  curl.cainfo at the kernel-installed CA bundle; add curl-https.spec.
- Raise the nginx-ready timeout to 180s and retry the wp-admin/install.php
  POST under load (loaded CI runners cold-start several kernels at once).

Ported down from the kandelo-beta branch (PR #3957) as the CLI-layer
slice of the stack rework.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch 2 times, most recently from 37e94b4 to fdc5117 Compare July 19, 2026 17:24
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch from 40cec0d to 03c71da Compare July 20, 2026 04:22
@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch from 4751714 to c4ee771 Compare August 11, 2026 16:35
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch 2 times, most recently from 682170a to a1b3822 Compare August 12, 2026 07:43
@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch 2 times, most recently from 4eb0a57 to bb3cad6 Compare August 12, 2026 10:31
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch from cb2f551 to d4ccbd6 Compare August 12, 2026 12:15
@mho22
mho22 marked this pull request as ready for review August 12, 2026 13:18
@mho22
mho22 requested a review from brandonpayton August 12, 2026 13:18
@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch from bb3cad6 to 4cb3c28 Compare August 13, 2026 12:33
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch from d4ccbd6 to 4019733 Compare August 13, 2026 14:58
@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch from 4cb3c28 to 687b9ee Compare August 24, 2026 11:01
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch from 4019733 to dfd6fda Compare August 24, 2026 11:01
@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch from 687b9ee to 0adbb30 Compare August 24, 2026 11:27
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch from dfd6fda to 847977b Compare August 24, 2026 11:27
@mho22 mho22 changed the title [wasm-posix-kernel] WordPress Playground Web Kandelo Beta [wasm-posix-kernel] WordPress Playground Web Kandelo Beta - Proof of concept Sep 9, 2026
@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch from 0adbb30 to 70b2f46 Compare October 18, 2026 11:07
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch from 847977b to be69ae0 Compare October 18, 2026 12:09
@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: aae8aa12-f1d8-4f5b-b194-fe4db06b6a48

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch from 70b2f46 to ceade5f Compare October 18, 2026 12:28
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch 2 times, most recently from efb9f7b to e17b4ee Compare October 18, 2026 13:05
@mho22
mho22 force-pushed the playground-web-experimental-posix-kernel branch from ceade5f to 3dfe080 Compare October 18, 2026 13:07
@mho22
mho22 force-pushed the playground-web-kandelo-beta branch from 4fc4e87 to e17b4ee Compare October 18, 2026 13:12
mho22 added 4 commits October 18, 2026 18:56
`assertLikelyCompatibleRemotePath` rejected every pathname except `/remote.html`, so a kernel-mode session pointing the iframe at `/remote-posix-kernel.html` threw "Invalid remote URL" before booting. The remote check now accepts both entries and the error message lists the accepted pathnames.
`getRemoteUrl` points the remote iframe at `/remote-posix-kernel.html` when `?experimental=kandelo` is present. The kernel remote needs `SharedArrayBuffer`, which browsers only grant on cross-origin isolated pages, so when the page is not isolated the website falls back to the classic runtime with a warning instead of failing inside the kernel worker.

`PlaygroundRoute.site` preserves the `experimental` param when it rewrites a stored-site URL — dropping it would silently switch opted-in sessions back to the classic runtime when selecting a saved site.
`/remote-posix-kernel.html` is served cross-origin isolated (COOP `same-origin`, COEP `require-corp`, Document-Isolation-Policy) so its worker can allocate `SharedArrayBuffer`. `/` and `/index.html` only opt into isolation when `?experimental=kandelo` is set, because COOP `same-origin` breaks the GitHub OAuth popup for everyone else; they use COEP `credentialless` to keep cross-origin subresources loading without CORP headers.

Dedicated worker scripts must carry a COEP header compatible with the document that spawns them; the dev server sets it on every response, production did not, so the kernel remote's workers and the website's OPFS workers failed to load. `playground_is_worker_script` serves the worker entries with COEP `require-corp`, which satisfies both the `require-corp` iframe and the `credentialless` parent, and keeps the hash-named files edge-cacheable.

`custom-redirects-lib.php` covers the PHP deployment and `.htaccess` mirrors the headers for the static one; `tests.php` covers the new branches.
… artifact

Adds the `build-experimental-posix-kernel` nx target and gives `vite.posix-kernel.config.ts` a build section: entry `remote-posix-kernel.html`, its own `dist/packages/playground/remote-posix-kernel` output so the classic and kernel asset graphs never overwrite each other, and the classic worker output rules so the shared service worker resolves to the same `/sw.js` — the artifact ships the classic-built copy.

The build needs the `kandelo/` submodule, which regular website builds do not check out, so it is not part of the website build graph: `deploy-website.yml` invokes the target before the website build; `build:wasm-wordpress-net` packages the output only when present. The kernel binaries come from `@wp-playground/posix-kernel-builds`.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant