MozaiksPay Provider Contract¶
MozaiksPay is the recommended managed monetization provider and the default for generated SaaS applications. It is not mandatory: an explicit entitlement_dispatch choice selects the self-managed OSS path, and a compatible provider can replace the hosted MozaiksPay service when it satisfies the same app-facing contract.
This contract describes the public boundary a canonical app depends on. It does not describe BlocUnited's hosted payment processor, wallet, payout, settlement, merchant operations, fee policy, credentials, or production authority internals.
Generated App Boundary¶
When Factory resolves monetization_provider: mozaiks_pay and the mozaikspay capability pack—by default or explicit choice—the generated app receives:
app/services/integrations/mozaikspay_client.pyapp/modules/billing_portal/- billing, usage, and pricing pages
app/config/subscriptions.yaml- names-only deployment/env handles
Pages call the app-owned billing_portal module. The module calls the generated MozaiksPayClient. The generated app must not call hosted product modules, payment-provider SDKs, wallet internals, payout internals, or settlement systems directly.
When the approved design assigns billing_portal to the MozaiksPay facade, AppGenerator's plan-review repair derives its generated_module capability from the pack contract before origin validation. The mozaikspay managed capability and its api_surface client task use a separate external-integration surface. The facade's actions and pages come from contract.yaml; its owned entities come from the approved design. Displaying subscriptions, runtime usage, or token balances does not make the facade their persistence owner.
A planner-created second facade name is consolidated only when its pages and actions are confined to the declared facade, it owns no entities, and it has no separately approved identity. It must also claim the facade surface or name facade pages without a separately approved surface. Task references and module paths then use billing_portal. Conflicting file owners still fail validation. Origin validation and the build journey order are unchanged.
generated page
-> billing_portal module action
-> services/integrations/mozaikspay_client.py
-> MozaiksPay-compatible provider API
Selection And Replacement Semantics¶
Factory defaults MozaiksPay for apps that need SaaS subscriptions, billing portal redirects, token top-ups, usage status, or paid feature gates. Selection is not activation: no account is created and the connector remains unconfigured until an operator supplies credentials. Non-subscription and explicitly self-managed apps receive no MozaiksPay artifacts.
The executable provider choices for subscription assignment are:
mozaiks_pay— the managed MozaiksPay-compatible provider path.entitlement_dispatch— the self-managed OSS subscription assignment writer.
These choices are mutually exclusive because only one path may own subscription assignment writes for config/subscriptions.yaml.
Replacement is supported at the provider boundary. A self-hosted or alternative provider must preserve the generated app contract:
- keep the
billing_portalfacade behavior compatible - serve the provider API paths used by
MozaiksPayClient - return the documented response fields
- avoid provider-internal identifiers in app-facing responses
- verify payment/subscription facts before applying provider-neutral effects
- preserve
app/config/subscriptions.yamlas the app plan and entitlement input
Replacing the provider does not imply compatibility with BlocUnited-private wallet, payout, settlement, merchant, or hosted billing operations.
Configuration¶
The generated client resolves provider configuration from the app-scoped mozaikspay connector and its scoped vault secret. Environment variable fallback for self-hosted/local operation applies only when no connector record exists. An incomplete saved connector, an unreadable secret, or a failed connector lookup raises a configuration error before a provider request. Reconnect the app's connector; process-wide credentials never fill its missing fields.
Public/app-facing handles:
MOZAIKSPAY_API_BASEMOZAIKS_APP_URL
Secret handles:
MOZAIKSPAY_API_KEYMOZAIKSPAY_CLIENT_IDMOZAIKSPAY_CLIENT_SECRET
Generated artifacts may declare these names. They must not contain raw API keys, client secrets, payment-provider credentials, private keys, connection strings, or hosted product credential topology.
Provider API Surface¶
The machine-readable source of truth is:
The current public endpoints consumed by generated apps are:
GET /api/mozaikspay/v1/subscription/statusPOST /api/mozaikspay/v1/billing-portal/sessionPOST /api/mozaikspay/v1/subscription/checkout-sessionPOST /api/mozaikspay/v1/tokens/top-up-sessionGET /api/mozaikspay/v1/health
The generated client authenticates with a MozaiksPay API key when configured, or with the compatibility client-credentials headers described in provider_api_contract.yaml.
Runtime usage status is read from the app runtime through MOZAIKS_APP_URL; it is not a hosted-provider ledger API.
Facade Actions¶
The generated billing_portal module exposes the app-facing actions:
get_subscription_statusget_usage_statusget_token_statuslist_plansstart_subscription_checkoutstart_token_top_upopen_billing_portal
Read actions require billing_portal.read. Checkout, top-up, and billing portal actions require billing_portal.manage.
Entitlement And Fulfillment Boundary¶
Generated apps express plans, limits, token allowances, token top-up products, and assignment storage in app/config/subscriptions.yaml.
A compatible provider owns only the external verified fact source. After a provider verifies a checkout, subscription change, or top-up, effects must cross into the app/runtime through provider-neutral fulfillment and entitlement boundaries such as BillingFulfillmentCommand, EntitlementPort, subscription assignment records, and the OSS token wallet ledger.
Provider callbacks must fail closed when malformed or unsigned. Replayed events must reuse the same idempotency key so BillingFulfillmentService can replay or reject duplicate fulfillment commands deterministically.
The generated app should not embed provider product IDs, provider customer IDs, payment processor IDs, wallet ledgers, payout ledgers, webhook handlers, or payment processor SDK calls.
Error Semantics¶
Provider responses must follow the response and error shapes in provider_api_contract.yaml.
Stable expectations:
- authentication failures use HTTP
401 - authorization failures use HTTP
403 - invalid app requests use HTTP
400 - missing app/customer/subscription facts use HTTP
404 - application-level failures return
success: falsewith safe error details
Responses must not expose raw secrets, provider customer IDs, provider subscription IDs, payment provider IDs, session IDs, secret hashes, or internal credential fields.