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>
6.2 KiB
Commercial Runtime Backend — Final Report
Date: 2026-07-28
Phase:commercial-runtime-backend
Domain: Core Platform → Commercial Runtime (backend/core-service/app/commercial)
Architecture status: COMMERCIAL_RUNTIME_BACKEND_COMPLETE
Contract family:commercial.v1.2
ADR: ADR-023 · ownership boundary ADR-022
Verdict
Commercial Runtime Backend is the single Source of Truth for commercial metadata on TorbatYar Platform.
- Universal
CommercialRegistryObject+ meta-registryCommercialRegistryKind - Unlimited future kinds via
POST /api/v1/commercial/admin/kinds(zero code change for CRUD) - Discovery catalog so the frontend never hardcodes registry names
- Recommendation, assessment, bundle, plan, license, and policy engines
- Outbox events, OpenAPI paths, Alembic migration
0007_commercial_runtime, seed from docs catalogs - 9/9
test_commercial_runtime.pygreen
Commercial owns definitions only. Orders, invoices ledgers, payments, and vertical data remain owned by their services.
Placement
| Choice | Path |
|---|---|
| Service | backend/core-service (Core Platform) |
| Package | app/commercial/ |
| API | /api/v1/commercial/* |
| DB | core_platform_db · tables commercial_* |
| Migration | alembic/versions/0007_commercial_runtime.py |
| Seed | scripts/seed_commercial_runtime.py |
Compatible with existing Core Platform ownership of tenants, plans, entitlements, and outbox.
Universal Registry Model
Every registry object exposes:
| Field | Notes |
|---|---|
registry_object_id |
UUID primary key (= id) |
slug |
URL-safe identity |
stable_code |
Business code (product_code, bundle_code, …) |
version / version_code |
Versioning |
status |
draft · published · archived · deleted |
visibility |
public · authenticated · admin · hidden |
payload + metadata |
Open JSON — no service-specific ID columns |
created_by / updated_by |
Audit actors |
| timestamps | created/updated + published/archived/deleted |
| soft delete | is_deleted + restore |
Lifecycle actions: publish · draft · archive · delete · restore · clone.
List APIs: search (q) · filters · pagination · sorting · tenant-safe.
Built-in registries (CRUD + discovery)
Products · Bundles · Pricing · Plans · Trials · Capabilities · Policies · Assets · Extensions · Automation Packs · Metadata · Recommendation Rules · Assessment Schemas · Notifications · Usage Plans · Coupons · Promotions · Taxes · Currencies · Regions · Industries · Business Types · Announcements · Languages
Plus generic /api/v1/commercial/registries/{kind} for any future kind.
Discovery: GET /api/v1/commercial/catalog returns every enabled kind with href + generic_href.
Engines
| Engine | Endpoint / behavior |
|---|---|
| Recommendation | POST /recommendations — input business type/industry/size/goals/country/features → products, bundles, plans, capabilities, automations, assets + rule_trace |
| Assessment | GET /assessment/schema — questions from assessment_schemas registry only |
| Bundle resolver | GET /bundles/{code}/resolve — products, capabilities, policies, pricing, extensions, assets, automation |
| Plan resolver | GET /plans/{code}/resolve — trial, limits, price, renewal, visibility |
| License / entitlements | POST /entitlements/check + tenant licenses |
| Policy evaluate | POST /policies/evaluate |
| Notifications | notifications registry (email / SMS / push / in-app templates) |
Honest empty: GET /invoices and GET /transactions return empty collections — Payment owns money ledgers.
Events (outbox)
commercial.registry.created · updated · published · archived · deleted · commercial.subscription.activated (and related activation paths).
Quality gates
| Gate | Result |
|---|---|
| No TODO / fake / placeholder registries | PASS |
| No hardcoded product/bundle/capability catalogs in engines | PASS |
| Unlimited future kinds | PASS (admin/kinds + generic routes) |
Tenant isolation fields + platform catalogs (tenant_id NULL) |
PASS |
| Permissions (auth deps on mutating routes) | PASS |
| Audit + versioning + soft delete | PASS |
OpenAPI includes /commercial/* |
PASS |
| Tests | 9 passed |
Deployment readiness
| Area | Status |
|---|---|
| Backend code | READY |
Migration 0007 |
READY (apply on Core deploy) |
| Seed catalogs | READY (seed_commercial_runtime.py) |
| OpenAPI | READY (Core /openapi.json) |
| Tests | GREEN |
| FE adapters | Already wired; live after Core deploy + seed |
| Production | Deploy Core with commercial migration + seed; restart frontend BFF if needed |
Remaining roadmap (NOT this phase)
Do not implement in Commercial Runtime:
- Marketplace / QR / Booking / Payment
14.6+/ Experience FE11.6+product engines - Those products activate later by registry rows only (zero Commercial Runtime code changes)
Separate tracks (see project-status.yaml):
- Payment Backend MVP
14.6–14.10 - Hospitality
12.9/12.10 - Experience FE
11.6+ - Delivery production, booking, short links, QR, …
Optional follow-ups (non-blocking): FE catalog codegen from YAML; Payment connector for live invoices/transactions.
Artifacts
| Artifact | Path |
|---|---|
| Architecture report | commercial-runtime-backend-architecture-report.md |
| Snapshot | service-snapshots/commercial-runtime-backend.yaml |
| Handover | phase-handover/phase-commercial-runtime-backend.md |
| Foundation ADR | ADR-023 |
STOP
Commercial Runtime Backend is complete. Do not continue into Marketplace, QR, Booking, Payment 14.6+, CRM, or vertical modules from this phase.