Skip to content

Persist functional WordPress state in Cloudflare#1886

Open
chubes4 wants to merge 82 commits into
mainfrom
fix/1838-cloudflare-bounded-browser
Open

Persist functional WordPress state in Cloudflare#1886
chubes4 wants to merge 82 commits into
mainfrom
fix/1838-cloudflare-bounded-browser

Conversation

@chubes4

@chubes4 chubes4 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Run a functional WordPress site in a Cloudflare Worker with PHP-WASM in the entry Worker, a lightweight Durable Object lease/CAS coordinator, canonical Markdown/JSON state in R2, and disposable reconstructed SQLite.

The runtime supports WordPress login, wp-admin, the block editor, authenticated publishing, public rendering, browser assets, serialized concurrent mutations, and cold reconstruction.

What changed

  • serialize canonical WordPress mutations through WordPressStateCoordinator
  • bootstrap and persist complete canonical MDI revisions in R2 while keeping SQLite disposable
  • materialize a bounded 1,810-file, 22,598,313-byte server corpus from WordPress 7.0.2
  • serve individual browser assets outside PHP through bounded archive reads
  • package the deterministic runtime corpus as a content-addressed R2 artifact
  • pin merged MDI PR Strengthen apply-back evidence fixture #139 and apply the temporary built overlay from WordPress Playground #4110 until it reaches a published package

Exact-head verification

Verified after merging current main at 05b9ba19:

  • npm install and workspace build: passed
  • npm run test:cloudflare-runtime: 18 passed
  • npm run test:cloudflare-wordpress-archive-corpus: passed against the real WordPress archive
  • npm run test:runtime-php-snippets: passed
  • npm run test:agent-task-contracts: passed
  • npm run cloudflare:dry-run: passed; 22,574.94 KiB / gzip 8,212.79 KiB
  • full kimaki tunnel --port 8792 -- npm run cloudflare:local-gate: passed under Wrangler/workerd

The full gate proves login, authenticated dashboard, real block editor, two serialized concurrent canonical mutations, authenticated REST publication, public post rendering, frontend/admin/editor CSS and JavaScript, static response semantics, Worker stop/start, persisted post recovery, and authenticated-session recovery.

The exact head is deployed at https://wp-codebox-cloudflare-runtime.chubes.workers.dev/. Live validation proved login, dashboard, editor, authenticated publication, public rendering, bounded browser assets, and recovery of the newly published post across two additional exact-revision deployments.

Architecture

Browser -> Cloudflare Worker (PHP-WASM + WordPress)
                    |             |
                    |             +-> bounded WordPress archive asset reads
                    |
                    +-> Durable Object (lease + pointer CAS only)
                                      |
                                      +-> R2 canonical MDI revisions
                                          + disposable SQLite reconstruction

Compatibility

Cloudflare runtime state changes from isolate-local mutable state to serialized canonical MDI revisions in R2. Existing health, state, synthetic mutation, and bounded boot-probe routes remain. The token-protected operator reset route is additive. No public package API is removed.

Source relationships

AI assistance

  • AI assistance: Yes
  • Tool: OpenCode
  • Model: openai/gpt-5.6-sol
  • Used for: diagnosis, implementation, Cloudflare runtime verification, merge reconciliation, and evidence capture

@chubes4

chubes4 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Cloudflare deployment orchestration is tracked in Extra-Chill/homeboy-extensions#2303. This PR is the first consumer: exact-revision deploy, login/publish/assets gate, same-revision redeploy, and MDI/R2 reconstruction proof.

@chubes4

chubes4 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Remote deployment evidence for exact commit 2dac41a06e68a43eab871c5d8f1f30766d6c9197:

  • Worker versions 16f64334-fa72-436c-b2a9-bfb83fed0df6 and 4602797d-b35e-467d-beb9-1eb62a87da3b deployed successfully.
  • The prior canonical pointer was backed up byte-for-byte to sites/default/markdown/backups/20260719T034654Z-pre-1886-current.json; only current.json was reset.
  • Fresh /wp-login.php bootstrap failed with Cloudflare 1101. Tail evidence: WordPressStateCoordinator outcome exceededMemory, exception Durable Object's isolate exceeded its memory limit and was reset, CPU 219650 ms, wall 237465 ms.
  • No new current.json was promoted.

Root cause: first boot converts the SQLite seed to canonical MDI files and then starts the canonical runtime inside one Durable Object isolate. The fix is to package a prebuilt canonical MDI seed so cold bootstrap creates only one PHP-WASM runtime from canonical files; SQLite remains disposable. Remote durability claims remain blocked until login/publish/redeploy passes.

@chubes4

chubes4 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up remote evidence for exact commit 7159cf0e72db3b674ca745cc0e0e604df1b6cd6f:

  • Deployed Worker version 4d6fe439-62b2-428e-b4dd-7085f4b79063.
  • Prebuilt canonical MDI seed removed runtime SQLite-to-MDI conversion and reduced failed bootstrap from 219650 ms CPU to 48406 ms CPU.
  • /wp-login.php still returned Cloudflare 1101. Tail: WordPressStateCoordinator outcome exceededMemory, exception Durable Object's isolate exceeded its memory limit and was reset, wall 53293 ms. No canonical pointer was promoted.

The remaining architectural issue is hosting PHP-WASM inside the Durable Object. The next correction keeps PHP-WASM in the entry Worker and restores the DO to a lightweight global lease/current-pointer CAS coordinator. Canonical MDI/R2 state and the prebuilt seed remain unchanged.

@chubes4

chubes4 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Remote evidence for exact commit c590c4af3f15d3d6a0c342c878855b4e7ce21652:

  • Deployed Worker version 5f560b41-52bd-4589-82cd-e65ae4ddba11.
  • PHP-WASM is no longer in the Durable Object; the DO remains a lightweight lease/CAS coordinator.
  • Entry Worker bootstrap still returned HTTP 503. Tail: outcome exceededMemory, exception Worker exceeded memory limit, CPU 36740 ms, wall 42410 ms.

The remaining memory source is the selected WordPress filesystem: the predicate currently includes every file under wp-admin/ plus duplicate unminified/minified browser assets. The next correction bounds the production corpus to PHP and production/minified assets required by login, dashboard, editor, and frontend routes while preserving filtered Range extraction.

@chubes4

chubes4 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Remote evidence for exact commit 8138eb144f68922e8426ba3d3d760133eb1f3c41:

  • Deployed Worker version 37092595-5ee5-48e9-9d7b-eb42345bec2b.
  • The production corpus dropped from 85.4 MB to 53.7 MB, but /wp-login.php still returned HTTP 503 / Cloudflare 1102. Tail: entry Worker exceededMemory, CPU 67340 ms, wall 74018 ms.

MEMFS overhead plus PHP-WASM still makes 53.7 MB too large. The next boundary keeps only server-executed PHP/templates/metadata in PHP MEMFS and serves individual static CSS/JS/font/image requests by exact bounded Range extraction from the WordPress archive. WordPress script concatenation will be disabled so browser assets do not need to live in PHP memory.

@chubes4

chubes4 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

Remote evidence for exact commit 36a6c1e5dd76c961760c34b8519f53453ca9e8d8 / version 8f8f7ae3-a171-4e57-a23d-27fa59f08d25:

  • The reduced 22.6 MB PHP corpus removed the prior memory exception.
  • /wp-login.php produced no response within 300 seconds; a second bounded request timed out at 90 seconds.
  • Version-filtered error tail had no completed event/exception.
  • ?phase=r2-state remained responsive with pointer null, version 0; direct R2 confirms no current.json.

The boot-critical dependency is now external multi-range assembly of 1,810 WordPress files. The correction moves the filtered server corpus into a deterministic deployment artifact stored in R2. Worker boot will stream one R2 object into MEMFS; browser assets remain lazy exact-range/cache requests.

@chubes4

chubes4 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

Final verification update

The diagnostic-free head 486bdf83 passes:

  • npm run test:cloudflare-runtime: 17/17
  • Cloudflare runtime TypeScript check
  • npm run cloudflare:dry-run
  • npm run test:runtime-php-snippets
  • deployed login, dashboard, real block editor, REST publish, public render, and unchanged-revision cold recovery

Two independent infrastructure/tooling gaps remain tracked:

No diagnostic routes or R2 stage artifacts from the investigation remain in the final Worker.

@chubes4

chubes4 commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator Author

Dev-rig and corpus repair pushed in f1ec68bb.

What changed

  • replaced the broken multi-range corpus generation path with one complete archive download plus local decodeZip() selection
  • strengthened the production archive contract against the real WordPress ZIP (4,401 entries, 1,810 selected files, 22,598,313 selected bytes)
  • made workerd readiness parsing ANSI-safe
  • added the exact built overlay from WordPress Playground #4110 at afea9c042999c65f5b43bc049ca4b2bea9d8b361; the patch is removable once a published package contains that change

Verification

  • npm run test:cloudflare-runtime: 18 passed
  • npm run test:cloudflare-wordpress-archive-corpus: passed against the real archive
  • npm run test:runtime-php-snippets: passed
  • npm run cloudflare:dry-run: passed, 22574.94 KiB / gzip: 8212.79 KiB
  • full kimaki tunnel --port 8792 -- npm run cloudflare:local-gate: passed corpus provisioning, concurrent mutations, dashboard/editor, publishing/public rendering, browser assets, cold restart, and MDI reconstruction
  • git diff --check: passed

No production deployment was performed.

…ounded-browser

# Conflicts:
#	package-lock.json
@chubes4

chubes4 commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator Author

Production deployment evidence

Exact head 05b9ba1930de9d3c6348ca9ee139b138c37046af is live at https://wp-codebox-cloudflare-runtime.chubes.workers.dev/.

  • provisioned immutable WordPress corpus runtime/wordpress/6fb95a94d5c06de7ddf35aba94cfc663d281ea500488e5c1206ec374f67a2173.zip to production R2
  • deployed through the tracked Homeboy cloudflare-workers rollback contract
  • final deployment: 87407afb-86d6-45bb-9263-521c167e76f1
  • final version: 9e906844-42d6-48f4-a60b-d9e9fcc65206 at 100% traffic
  • health, login form, and prior persisted post passed after deployment and same-revision redeploy
  • authenticated login redirected 302; dashboard and block editor returned 200
  • authenticated REST publication returned 201
  • new public post returned 200; representative CSS and JavaScript passed through the bounded archive path
  • the new post survived two additional exact-revision deployments; health, login, and post gates returned 200 on the final version

One login-form request during cold reconstruction returned a transient 500; the declared bounded retry succeeded with 200. A parallel post-deploy probe also encountered lease contention, then serial login, dashboard, editor, and public-post verification all returned their expected success statuses. No rollback was required.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a Cloudflare-hosted Playground runtime backend

1 participant