This candidate integration for wp-codebox#1838 runs WordPress through PHP-WASM and Playground in Cloudflare Workers.
The entry Worker executes PHP-WASM and WordPress. Runtime behavior depends on the typed RevisionCoordinator contract rather than a Cloudflare storage product. The standard worker-do.ts entrypoint injects the existing WordPressStateCoordinator Durable Object adapter. The ChatGPT Sites-compatible worker-d1.ts entrypoint injects a D1 adapter that stores only the current pointer, version, lease token, lease base, and expiry in one conditional-update row. Both adapters serialize the same bounded lease and CAS promotion semantics; neither imports or instantiates PHP-WASM. MDI, disposable SQLite, and canonical R2 storage are unchanged.
On cold start, the entry Worker uses the acquired pointer to rebuild PHP-WASM's disposable SQLite index from canonical MDI Markdown and JSON files. A missing pointer materializes the packaged canonical MDI seed and boots one PHP-WASM primary runtime. The build-time PHP CLI generator creates that archive from wordpress-install-seed.sqlite through MDI's public bootstrap_existing_cache() API, validates its pinned MDI revision and input digest, and never packages SQLite. The runtime updates siteurl and home through WordPress APIs using the request origin and sets the admin password from WORDPRESS_ADMIN_PASSWORD; only WordPress's password hash is canonical. Bootstrap persists and CAS-promotes this mutation before serving the next request.
Canonical browser, health, and mutation boots require the separately managed WORDPRESS_AUTH_SECRET Worker secret. The entry Worker derives the eight WordPress auth keys and salts from that secret with a versioned, site-scoped (default) SHA-256 domain separator before wp-load.php. It never logs, persists, or returns the secret or derived values. Configure it independently from the bootstrap password with wrangler secret put WORDPRESS_AUTH_SECRET --config packages/runtime-cloudflare/wrangler.jsonc; rotating WORDPRESS_ADMIN_PASSWORD does not rotate authentication salts or invalidate sessions.
After each mutating HTTP request, the entry runtime invokes MDI's explicit request-boundary flush, collects canonical files, stores immutable content-addressed R2 objects and a revision manifest, then commits the new pointer through the held lease. GET, HEAD, and asset requests release without promotion. Failed requests abort their leases; stale leases recover by token/version/expiry checks. The entry isolate can cache one runtime only for the exact acquired pointer revision and exits it after promotion or when another isolate advances the pointer. It does not persist SQLite. Existing manifests are reused when canonical file hashes have not changed.
Anonymous HTML responses are stored as create-once, host-independent R2 artifacts under their canonical revision. An authorized POST ?phase=operator-publish promotes a bounded, sorted set of already-rendered routes by writing an immutable publication descriptor and then replacing one strongly consistent sites/default/publications/current.json pointer. Published GET and HEAD requests check a 60-second edge entry and then the R2 publication before constructing the Durable Object stub; authenticated, preview, admin, REST, and unpublished routes continue through WordPress. Promotion rejects missing, stale, duplicate, malformed, or conflicting artifacts. This is the coordinator-free reader boundary, not yet a complete route compiler or global CDN purge pipeline.
The same revision transaction persists bounded user-managed files under wp-content/plugins, themes, languages, and mu-plugins. Runtime-owned MDI, SQLite integration, and Codebox adapter files remain reconstructable artifacts and are excluded. Unchanged bundled-theme files are omitted by release hash, while modified files become canonical overrides. Public canonical plugin and theme assets serve directly from revision-addressed R2 cache entries before the immutable release corpus. Nonce-protected wp-admin GET actions such as plugin activation are classified as mutations so their filesystem and MDI option changes commit atomically. Existing revisions without wpContent remain valid.
The Worker forwards browser cookies directly to Playground and disables Playground's internal cookie store, preventing an empty per-isolate store from replacing a valid browser session after cold restart.
A minute Cloudflare Cron Trigger drains at most five due WordPress events or 25 seconds of work per invocation. Each event receives its own Durable Object lease and canonical R2 revision transaction. Direct /wp-cron.php requests are disabled so callbacks cannot bypass that transaction boundary.
The bundled MDI source is pinned to immutable commit bf6d434d1673fdd86d777501f7eaec292d32ad1f, including MDI PR #141. The bundle generator, worker provenance, and source-contract test use the same revision.
WordPress server files, browser assets, and pinned runtime dependencies are separate deployment artifacts, never Worker-module imports. generate:cloudflare-wordpress-runtime-corpus emits a deterministic server ZIP containing only isWordPressRuntimeFile() entries, one concatenated browser-asset blob containing the complete supported wp-admin, wp-includes, and bundled-theme surface, and the pinned SQLite integration ZIP. Checked-in manifests record content-addressed R2 keys, hashes, budgets, provenance, and each browser asset's exact byte range. Cold boot validates and streams the server ZIP into PHP MEMFS while loading SQLite integration from R2. Browser requests use one bounded R2 range read, validate the selected bytes, and populate an immutable artifact-versioned Worker cache. Runtime requests never fetch WordPress or SQLite integration release archives from third-party origins.
Canonical Cloudflare boots patch only the assembled PHP MEMFS copy of /wordpress/wp-settings.php after the R2 WordPress corpus is materialized and before WordPress executes. The disabled-cron scheduling policy requires exactly one canonical do_action( 'init' ); needle and fails closed otherwise. When DISABLE_WP_CRON is true, it removes only core's wp_cron, wp_schedule_delete_old_privacy_export_files, and wp_schedule_update_checks callbacks through public remove_action() before executing the original init call once. This prevents browser requests from recreating cron work that cannot execute in the PHP-WASM/MDI shutdown path. Durable cron execution belongs to a separate explicit queue or scheduled-Worker contract.
- Run
npm run generate:cloudflare-canonical-mdi-seedandnpm run generate:cloudflare-wordpress-runtime-corpusto regenerate deterministic runtime artifacts and manifests. - Run
npm run provision:cloudflare-wordpress-runtime-corpus -- --local --persist-to <directory>to verify and upload all exact content-addressed artifacts into isolated local R2 storage. For an authorized deployment, run the provisioner with--remoteand require every upload to succeed before deploying the Worker that imports their manifests. - Run
npm run test:cloudflare-runtimefor routing, coordinator composition, canonical-state, artifact validation, source contract, and TypeScript coverage. - Run
npm run cloudflare:dry-runandnpm run cloudflare:dry-run:d1to compile the Durable Object and D1 profiles without creating Cloudflare resources. The placeholder D1 database ID is for local/dry-run verification; an implementation supplies its provisioned binding at deployment. - Run
npm run cloudflare:local-gateandnpm run cloudflare:local-gate:d1for the same isolated workerd workflow through both coordinator implementations. Each gate generates and provisions all artifacts, verifies the selected backend through the state envelope, injects stable test-only admin-password, auth-secret, and operator-token values, uploads and activates a real plugin ZIP, promotes anonymous homepage and canonical-permalink artifacts, and proves an R2 publication read after Worker restart. They also cover login, concurrent canonical writes, authenticated REST publication, media, representative frontend/admin/editor assets, PHP diagnostics, session recovery, cron, and a fresh login after restart.
This document describes local candidate verification only. It does not claim remote deployment.