Unify commercial runtime ownership across backend and frontend so platform, experience, and hospitality modules use the shared commercial source of truth. Co-authored-by: Cursor <cursoragent@cursor.com>
3.0 KiB
Commercial Runtime Backend — Architecture Report
Date: 2026-07-28
Phase:commercial-runtime-backend
Normative: commercial-platform-architecture.md, ADR-023, ADR-022
Decision
Commercial Runtime is implemented inside Core Platform (backend/core-service), not as a separate microservice.
Rationale:
- Core already owns tenants, entitlements projection, onboarding, audit, and outbox
- Commercial metadata is platform-scoped SoT, not a vertical product
- Single deployable + shared JWT/tenant middleware
- Avoids a new network hop for every FE commercial adapter
Ownership boundary (ADR-022 / ADR-023)
| Owns | Does not own |
|---|---|
| Products, bundles, pricing definitions, plans, trials | Orders |
| Capabilities, policies, assets, extensions, automation packs | Invoices / payment ledgers |
| Metadata, recommendations rules, assessment schemas | Accounting journals |
| Notification templates, usage plans, coupons, promotions | CRM / Experience / Delivery / Hospitality / Healthcare / Beauty data |
| Taxes, currencies, regions, industries, business types | PSP callbacks / settlement |
Money movement remains Payment. Vertical operational data remains vertical services.
Layering
API app/api/v1/commercial.py
→ CommercialRegistryService / resolvers / recommendation
→ CommercialRepository
→ CommercialRegistryObject | Kind | Subscription | License | Activation
→ OutboxEvent + Audit
Meta-registry (CommercialRegistryKind) drives discovery. Builtin path aliases register convenience routes; unknown future kinds use /registries/{kind} only.
Expansion rule
New commercial object type = DB row in commercial_registry_kinds + registry objects.
No backend code change required for CRUD, search, lifecycle, or catalog discovery.
New product (Marketplace, QR, Booking, …) = published registry records (product + capabilities + pricing + optional bundle refs).
No Commercial Runtime code change.
Tenant model
- Platform catalogs:
tenant_id IS NULL - Tenant-scoped commercial rows (subscriptions, licenses, activation):
tenant_idset - List/search default platform_only for public catalogs; mutating routes require auth
Compatibility
- Contract family
commercial.v1.2 - FE module
frontend/modules/commercialconsumes/api/v1/commercial/* - Seed imports from
docs/reference/*catalogs (idempotent)
Related
Final report: commercial-runtime-backend-final-report.md
Cleanup / sole SoT: commercial-runtime-cleanup-report.md · commercial-source-of-truth-report.md · commercial-runtime-final-certification.md