- Shipped
- August 8, 2026 at 8:44 PM UTC
- Author
- Kamo
- Commit
- bed209b
Nine apps — POS, Marketing Tools, Calculator, Club, Inventory, Legal, Games and the two origination systems — had no catalog representation at all: no pricing row, no category, no tier. Twelve others were already described by a marketing row, so binding those and adding a parallel APP_* row would have given one ServiceType two rows and made planFeatureIncluded depend on iteration order. The runner now converges the catalog instead: - binds a published marketing row to the app it describes (VIDEO_CONF is Meet, MESSAGING is Chat), keeping its code, name, category and tier values so the published matrix does not move; - creates a row for an app the catalog does not describe, in a real category — including a new Commerce & Origination category; - promotes any earlier APP_* placeholder to its real identity and deletes the flat Applications bucket once empty; - removes duplicate rows for the same app, preferring the marketing row. There is no APP_ fallback left: every app has a readable code, and apps the published catalog already names reuse that exact code so an org with its own matrix and one without describe the same product identically. That mattered — sign.pink has no marketing matrix and was left with eleven rows named after enum constants. MLOS and Personal Loans are enterprise-negotiated, not per-seat: null price, FLAT pricing model, compatible only with CUSTOM-type plans (Enterprise), bundled into no tier. They are created on the platform org only — a white-label product org does not resell them, and the two created on sign.pink by an earlier pass are deactivated. Verified against prod after running: 0 APP_* codes left, 0 duplicate service_type rows, 21 apps on each root, 0 uncovered plan-by-app combinations, and a re-run is a no-op.