ADR-001 Phase 3.5 PR-4 — Disable tenant-side Checkout in sovereign mode; redirect to main-site checkout
For #1250. Cross-repo parent: Ultimate-Multisite/ultimate-multisite-multi-tenancy#43.
Architectural decision
Checkout always runs on the main site. Sovereign tenants are the result of a checkout, not its host. Tenant-side checkout AJAX, form rendering, cart, and signup-field validators are all disabled in sovereign tenants; users who land on a checkout URL inside a sovereign tenant are redirected to the main site's /register/ page (or equivalent).
This eliminates the largest single risk surface in the Phase 3.1 audit (§2.7.5: tenant-AJAX wu_create_order writing across wu_payments, wu_customers, wu_memberships, wp_users simultaneously) without porting any of that logic to REST.
Files
| File |
Change |
inc/checkout/class-checkout.php |
Guard the 4 AJAX handlers at :199-222 (wu_create_order, wu_validate_form, wu_check_user_exists, wu_inline_login). In sovereign context, return JSON error pointing caller to main-site checkout URL. |
inc/checkout/class-checkout-pages.php |
When sovereign, replace tenant checkout/registration URLs with the main-site equivalent (resolve via get_network()->site_id → get_blog_details( $main_site_id )->siteurl . '/register/'). |
inc/checkout/class-cart.php |
Guard model loading; the Cart class should not instantiate / hit the DB in a sovereign tenant context. |
inc/checkout/class-legacy-checkout.php |
Same as class-checkout.php — guard hook registration. |
Reference pattern
For AJAX handlers:
public function wu_create_order() {
if ( defined( 'WU_MT_SOVEREIGN_TENANT' ) && WU_MT_SOVEREIGN_TENANT ) {
wp_send_json_error( [
'code' => 'sovereign_checkout_disabled',
'message' => __( 'Checkout runs on the main site.', 'wp-ultimo' ),
'main_site_url' => $this->get_main_site_checkout_url(),
], 400 );
return;
}
// ...existing body...
}
For URL replacement helper (new method on Checkout_Pages):
public function get_main_site_checkout_url(): string {
$main_site = get_blog_details( get_network()->site_id );
if ( ! $main_site ) {
return network_site_url( '/register/' );
}
return trailingslashit( $main_site->siteurl ) . 'register/';
}
UX requirement
Pages that previously rendered checkout forms or upgrade buttons inside sovereign tenants must render a clear "Upgrade on the main site" link instead of erroring or rendering an empty form. Wherever a checkout shortcode / block / element would render, replace its output in sovereign context with:
<a href="{main_site_checkout_url}" class="wu-sovereign-checkout-link">
Upgrade your plan on the main site
</a>
Tenant admins and customers see a working link, not a broken form.
Verification
- Non-sovereign tenant: checkout works exactly as before. Existing E2E tests green.
- Sovereign tenant — AJAX:
wu_create_order POST returns 400 sovereign_checkout_disabled with main_site_url in the response.
- Sovereign tenant — page render: any URL that previously rendered a checkout form renders the "Upgrade on the main site" link with a working URL.
- Sovereign tenant — Cart class not instantiated: confirm via debug log or unit test that
Cart::__construct is never called during a sovereign tenant request.
- Main site: checkout flow on the main site works unchanged.
Branch
dev-main integration branch.
LOC estimate
~50 lines across 4 files, mostly guards + the URL helper.
Tier
tier:2 — multi-file, requires UX decisions for the "Upgrade on main site" replacement element.
aidevops.sh v3.17.27 plugin for OpenCode v1.15.7 with claude-haiku-4-5 spent 5h 48m and 38 tokens on this as a headless worker.
ADR-001 Phase 3.5 PR-4 — Disable tenant-side Checkout in sovereign mode; redirect to main-site checkout
For #1250. Cross-repo parent: Ultimate-Multisite/ultimate-multisite-multi-tenancy#43.
Architectural decision
Checkout always runs on the main site. Sovereign tenants are the result of a checkout, not its host. Tenant-side checkout AJAX, form rendering, cart, and signup-field validators are all disabled in sovereign tenants; users who land on a checkout URL inside a sovereign tenant are redirected to the main site's
/register/page (or equivalent).This eliminates the largest single risk surface in the Phase 3.1 audit (§2.7.5: tenant-AJAX
wu_create_orderwriting acrosswu_payments,wu_customers,wu_memberships,wp_userssimultaneously) without porting any of that logic to REST.Files
inc/checkout/class-checkout.php:199-222(wu_create_order,wu_validate_form,wu_check_user_exists,wu_inline_login). In sovereign context, return JSON error pointing caller to main-site checkout URL.inc/checkout/class-checkout-pages.phpget_network()->site_id→get_blog_details( $main_site_id )->siteurl . '/register/').inc/checkout/class-cart.phpinc/checkout/class-legacy-checkout.phpclass-checkout.php— guard hook registration.Reference pattern
For AJAX handlers:
For URL replacement helper (new method on
Checkout_Pages):UX requirement
Pages that previously rendered checkout forms or upgrade buttons inside sovereign tenants must render a clear "Upgrade on the main site" link instead of erroring or rendering an empty form. Wherever a checkout shortcode / block / element would render, replace its output in sovereign context with:
Tenant admins and customers see a working link, not a broken form.
Verification
wu_create_orderPOST returns400 sovereign_checkout_disabledwithmain_site_urlin the response.Cart::__constructis never called during a sovereign tenant request.Branch
dev-mainintegration branch.LOC estimate
~50 lines across 4 files, mostly guards + the URL helper.
Tier
tier:2 — multi-file, requires UX decisions for the "Upgrade on main site" replacement element.
aidevops.sh v3.17.27 plugin for OpenCode v1.15.7 with claude-haiku-4-5 spent 5h 48m and 38 tokens on this as a headless worker.