Free Edition Upgrade Bridge API

This developer note documents the paid BricksMembers compatibility bridge for sites upgrading from Members for Bricks Builder. The bridge keeps the Free storage contract readable, deactivates the Free plugin when both are active, enables paid payment modules when Free Stripe EasySync data exists, and preserves the old EasySync webhook route.

Runtime Owners

  • BaselMedia\BricksMembers\FreeEdition\FreeEditionUpgradeService owns paid-side Free contract detection, Free plugin deactivation, payment-module enablement, and admin notices.
  • BaselMedia\BricksMembers\FreeEdition\EasySyncWebhookAliasController owns the paid compatibility route at /wp-json/bricksmembers/v1/stripe-easysync/webhook.
  • BaselMedia\BricksMembers\Modules\Payments\PaymentsWebhookController remains the canonical paid Stripe webhook processor. The EasySync alias delegates to it instead of duplicating Stripe signature or billing mutation logic.

Free Contract Detection

The paid runtime treats the install as Free-compatible when any of these markers exist:

  • brm_free_edition_installed
  • brm_free_storage_contract_version
  • brm_stripe_easy_enabled

Do not call Free plugin classes from the paid plugin. The paid bridge reads the documented options and shared BRM tables only.

Admin Upgrade Flow

  1. Plugin::register_hooks() boots FreeEditionUpgradeService.
  2. On admin_init, the service deactivates members-for-bricks-builder/members-for-bricks-builder.php when the current user can activate plugins and both plugins are active.
  3. If brm_stripe_easy_enabled is true, the service enables brm_enable_payments and brm_enable_payments_stripe.
  4. The service writes brm_free_contract_imported_at once and stores a one-time notice in brm_free_upgrade_bridge_notice.

Compatibility REST Route

The route POST /wp-json/bricksmembers/v1/stripe-easysync/webhook is registered only when a Free contract marker exists. Its REST permission callback is public for the same reason native provider webhooks are public: provider signature validation belongs inside the delegated Stripe webhook controller.

If paid Payments or paid Stripe is not active, the alias returns 503 with an explanatory message. Otherwise it passes the request to PaymentsWebhookController::handle_webhook_stripe().

Storage Contract

The bridge relies on the Free package using paid-compatible storage for core membership data:

  • brm_levels
  • brm_user_level_assignments
  • brm_post_level_requirements
  • brm_post_data
  • brm_payments_settings.providers.stripe
  • brm_payments_offers

Free-only Stripe ledgers, such as brm_free_stripe_entitlements and brm_free_stripe_events, remain compatibility data unless a later migration explicitly imports them into paid billing rows.

Implementation Rules

  • Do not duplicate Stripe signature validation in the alias controller.
  • Do not add a second billing mutation path for Free events. Delegate to the paid Payments webhook controller.
  • Do not depend on Free PHP classes being loaded after paid BricksMembers is active.
  • Keep user-facing upgrade notices one-time and dismissible. The bridge should not create a permanent dashboard warning after the contract has been imported.
Get BricksMembers

Start Building Your Membership Site Today

Create, sell, and manage your content without limits. BricksMembers gives you everything you need to build membership and LMS sites with Bricks Builder.

Lifetime updates & bug fixes • Premium support • 0% transaction fees • 60-day money-back guarantee