← back to All Designerwallcoverings
live-stock coverage audit: classify all 254 display-vendors into feasibility tiers (data/live-stock-coverage.json + scripts/build-coverage.js)
93e37e27db451b26c8e2eaf1c70d9e59cd611ec3 · 2026-07-07 09:23:12 -0700 · Steve
Files touched
A data/live-stock-coverage.jsonA scripts/build-coverage.js
Diff
commit 93e37e27db451b26c8e2eaf1c70d9e59cd611ec3
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Jul 7 09:23:12 2026 -0700
live-stock coverage audit: classify all 254 display-vendors into feasibility tiers (data/live-stock-coverage.json + scripts/build-coverage.js)
---
data/live-stock-coverage.json | 2809 +++++++++++++++++++++++++++++++++++++++++
scripts/build-coverage.js | 217 ++++
2 files changed, 3026 insertions(+)
diff --git a/data/live-stock-coverage.json b/data/live-stock-coverage.json
new file mode 100644
index 0000000..a03c611
--- /dev/null
+++ b/data/live-stock-coverage.json
@@ -0,0 +1,2809 @@
+{
+ "generated_at": "2026-07-07T16:22:59.582Z",
+ "generator": "scripts/build-coverage.js",
+ "total_display_vendors": 254,
+ "counts": {
+ "PORTAL_CREDS": 5,
+ "PUBLIC_STOCK": 12,
+ "PORTAL_NO_CREDS": 30,
+ "QUOTE_ONLY": 35,
+ "NO_STOCK": 172,
+ "live_capable": 13
+ },
+ "vendors": {
+ "1838 Wallcoverings": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": true,
+ "adapter": "shopify-public",
+ "reason": "public Shopify storefront stock (.js feed)",
+ "catalog_table": "w1838_catalog",
+ "backing": "1838 Wallcoverings",
+ "match": "exact",
+ "products": 481,
+ "active": 465
+ },
+ "420 Studios": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "A.S. Création": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 1
+ },
+ "Abel Macias": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "Alan Campbell": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Alan Campbell",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Ananbo": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Ananbo",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Andrew Martin": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "andrew_martin_catalog",
+ "backing": "Andrew Martin",
+ "match": "exact",
+ "products": 7,
+ "active": 5
+ },
+ "Anna French": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "anna_french_catalog",
+ "backing": "Anna French",
+ "match": "exact",
+ "products": 1108,
+ "active": 814
+ },
+ "Apartment Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 101,
+ "active": 39
+ },
+ "Architectural Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 483,
+ "active": 328
+ },
+ "Architectural Wallcoverings": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 9,
+ "active": 4
+ },
+ "Armani Casa": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "armani_casa_catalog",
+ "backing": "Armani Casa",
+ "match": "exact",
+ "products": 226,
+ "active": 0
+ },
+ "Armani/Casa": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 9,
+ "active": 0
+ },
+ "Arte": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 3,
+ "active": 0
+ },
+ "Arte International": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "arte_catalog",
+ "backing": "Arte International",
+ "match": "exact",
+ "products": 631,
+ "active": 523
+ },
+ "Artmura": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 161,
+ "active": 144
+ },
+ "AS Creation": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "as_creation_catalog",
+ "backing": "AS Creation",
+ "match": "exact",
+ "products": 505,
+ "active": 327
+ },
+ "Atomic 50 Ceilings": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "atomic50_catalog",
+ "backing": "Atomic 50 Ceilings",
+ "match": "exact",
+ "products": 2,
+ "active": 2
+ },
+ "Backdrop": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Backdrop",
+ "match": "exact",
+ "products": 9,
+ "active": 9
+ },
+ "Baker Lifestyle": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "baker_lifestyle_catalog",
+ "backing": "Baker Lifestyle",
+ "match": "exact",
+ "products": 8,
+ "active": 4
+ },
+ "Belarte Studio": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 11,
+ "active": 0
+ },
+ "Bespoke": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 632,
+ "active": 0
+ },
+ "Big Sur Beans": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 3,
+ "active": 0
+ },
+ "Black Edition": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "black_edition_catalog",
+ "backing": "Black Edition",
+ "match": "exact",
+ "products": 5,
+ "active": 3
+ },
+ "Boråstapeter": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 32,
+ "active": 31
+ },
+ "Boråstapeter Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 2,
+ "active": 0
+ },
+ "Brand McKenzie": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "brand_mckenzie_catalog",
+ "backing": "Brand McKenzie",
+ "match": "exact",
+ "products": 165,
+ "active": 156
+ },
+ "British Walls": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "british_walls_catalog",
+ "backing": "British Walls",
+ "match": "exact",
+ "products": 506,
+ "active": 472
+ },
+ "Brunschwig & Fils": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "brunschwig_catalog",
+ "backing": "Brunschwig & Fils",
+ "match": "exact",
+ "products": 3371,
+ "active": 2761
+ },
+ "Carlisle & Co. Walls": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": true,
+ "adapter": "shopify-public",
+ "reason": "public Shopify storefront stock (.js feed)",
+ "catalog_table": "carlisle_catalog",
+ "backing": "Carlisle & Co",
+ "match": "suffix-strip",
+ "products": 441,
+ "active": 0
+ },
+ "Caroline Cecil Textiles": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 6,
+ "active": 3
+ },
+ "Catchii Netherlands Europe": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 1
+ },
+ "Celerie Kemble": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "vendor_catalog",
+ "backing": "Celerie Kemble",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Charles Burger": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Charles Burger",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "China Seas": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "china_seas_catalog",
+ "backing": "China Seas",
+ "match": "exact",
+ "products": 1806,
+ "active": 1776
+ },
+ "China Seas Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "china_seas_catalog",
+ "backing": "China Seas",
+ "match": "suffix-strip",
+ "products": 2,
+ "active": 0
+ },
+ "China Seas Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "china_seas_catalog",
+ "backing": "China Seas",
+ "match": "suffix-strip",
+ "products": 2,
+ "active": 0
+ },
+ "Christian Lacroix Europe": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 175,
+ "active": 170
+ },
+ "Clarence House": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": null,
+ "backing": "Clarence House",
+ "match": "exact",
+ "products": 2,
+ "active": 2
+ },
+ "Clarke and Clarke": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "clarke_clarke_catalog",
+ "backing": "Clarke And Clarke",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Clarke And Clarke": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "clarke_clarke_catalog",
+ "backing": "Clarke And Clarke",
+ "match": "exact",
+ "products": 3927,
+ "active": 3573
+ },
+ "Cloth and Paper": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Cloth and Paper",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "CMO Paris": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "cmo_paris_catalog",
+ "backing": "CMO Paris",
+ "match": "exact",
+ "products": 1,
+ "active": 0
+ },
+ "Cole & Son": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "coleson_catalog",
+ "backing": "Cole & Son",
+ "match": "exact",
+ "products": 1268,
+ "active": 1238
+ },
+ "Colefax and Fowler": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 361,
+ "active": 0
+ },
+ "Contrado": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "contrado_catalog",
+ "backing": "Contrado",
+ "match": "exact",
+ "products": 19,
+ "active": 15
+ },
+ "Coordonn��": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 1
+ },
+ "Coordonné": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "coordonne_catalog",
+ "backing": "Coordonné",
+ "match": "exact",
+ "products": 1353,
+ "active": 1336
+ },
+ "Coordonné Europe": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "coordonne_catalog",
+ "backing": "Coordonné",
+ "match": "suffix-strip",
+ "products": 29,
+ "active": 0
+ },
+ "Cowtan & Tout": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "cowtan_tout_catalog",
+ "backing": "Cowtan & Tout",
+ "match": "exact",
+ "products": 453,
+ "active": 0
+ },
+ "Daisy Bennett": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Daisy Bennett",
+ "match": "exact",
+ "products": 70,
+ "active": 68
+ },
+ "Dedar": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "dedar_catalog",
+ "backing": "Dedar",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Designer Wallcoverings": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "folia_catalog",
+ "backing": "Folia Fabrics",
+ "match": "private-label",
+ "products": 2262,
+ "active": 1532
+ },
+ "Designer Wallcoverings and Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 15,
+ "active": 0
+ },
+ "Designers Guild": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "designers_guild_catalog",
+ "backing": "Designers Guild",
+ "match": "exact",
+ "products": 879,
+ "active": 853
+ },
+ "Designtex": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "designtex_catalog",
+ "backing": "Designtex",
+ "match": "exact",
+ "products": 317,
+ "active": 288
+ },
+ "Dolce & Gabbana": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "dolce_gabbana_catalog",
+ "backing": "Dolce & Gabbana",
+ "match": "exact",
+ "products": 36,
+ "active": 27
+ },
+ "Donghia": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "donghia_catalog",
+ "backing": "Donghia",
+ "match": "exact",
+ "products": 161,
+ "active": 157
+ },
+ "Dupenny": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Dupenny",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "DW Bespoke Murals": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "DW Bespoke Studio": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "bespoke_catalog",
+ "backing": "DW Bespoke Studio",
+ "match": "exact",
+ "products": 2331,
+ "active": 921
+ },
+ "DW Bespoke Studio To Go": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 9,
+ "active": 0
+ },
+ "DW Bespoke Studios To Go": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 592,
+ "active": 0
+ },
+ "DW Exclusive Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 1
+ },
+ "DW Home": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 79,
+ "active": 37
+ },
+ "DW Internal": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "DWHD": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 1
+ },
+ "Edge Wallcovering": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Edge",
+ "match": "suffix-strip",
+ "products": 1,
+ "active": 1
+ },
+ "Edge Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Edge",
+ "match": "suffix-strip",
+ "products": 1,
+ "active": 0
+ },
+ "Elitis": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "elitis_catalog",
+ "backing": "Elitis",
+ "match": "exact",
+ "products": 244,
+ "active": 243
+ },
+ "Emiliana Parati": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Emiliana Parati",
+ "match": "exact",
+ "products": 15,
+ "active": 1
+ },
+ "Erika Wakerly": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Erika Wakerly",
+ "match": "exact",
+ "products": 2,
+ "active": 2
+ },
+ "Et Cie Wall Panels": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 461,
+ "active": 0
+ },
+ "F. Schumacher Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 67,
+ "active": 0
+ },
+ "Fabricut": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "fabricut_catalog",
+ "backing": "Fabricut",
+ "match": "exact",
+ "products": 46,
+ "active": 3
+ },
+ "FallingStar Studio": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 42,
+ "active": 42
+ },
+ "Farrow & Ball": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "farrow_ball_catalog",
+ "backing": "Farrow & Ball",
+ "match": "exact",
+ "products": 2,
+ "active": 1
+ },
+ "Fentucci": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "fentucci_catalog",
+ "backing": "Fentucci",
+ "match": "exact",
+ "products": 2950,
+ "active": 358
+ },
+ "Fentucci Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "fentucci_catalog",
+ "backing": "Fentucci",
+ "match": "suffix-strip",
+ "products": 379,
+ "active": 0
+ },
+ "Fentucci Murals": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "fentucci_catalog",
+ "backing": "Fentucci",
+ "match": "suffix-strip",
+ "products": 8,
+ "active": 0
+ },
+ "Fentucci Naturals": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "fentucci_naturals_catalog",
+ "backing": "Fentucci Naturals",
+ "match": "exact",
+ "products": 148,
+ "active": 0
+ },
+ "Fentucci Naturals Walls": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "fentucci_naturals_catalog",
+ "backing": "Fentucci Naturals",
+ "match": "suffix-strip",
+ "products": 38,
+ "active": 0
+ },
+ "Fentucci Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "fentucci_catalog",
+ "backing": "Fentucci",
+ "match": "suffix-strip",
+ "products": 15,
+ "active": 0
+ },
+ "Flavor Paper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": null,
+ "backing": "Flavor Paper",
+ "match": "exact",
+ "products": 65,
+ "active": 0
+ },
+ "Florence Broadhurst": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": null,
+ "backing": "Florence Broadhurst",
+ "match": "exact",
+ "products": 25,
+ "active": 0
+ },
+ "Florentina Feathers": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 43,
+ "active": 0
+ },
+ "Franquemont London": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 26,
+ "active": 26
+ },
+ "French Market": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "French Market",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "G P & J Baker": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 2,
+ "active": 1
+ },
+ "Gaston Y Daniela": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "gaston_daniela_catalog",
+ "backing": "Gaston Y Daniela",
+ "match": "exact",
+ "products": 2293,
+ "active": 2151
+ },
+ "Glambeads by DW": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 59,
+ "active": 58
+ },
+ "Glass Beaded": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 107,
+ "active": 39
+ },
+ "Glitter Walls": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "glitter_walls_catalog",
+ "backing": "Glitter Walls (multi-source)",
+ "match": "private-label",
+ "products": 551,
+ "active": 403
+ },
+ "GP & J Baker": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "gp_baker_catalog",
+ "backing": "GP & J Baker",
+ "match": "exact",
+ "products": 1885,
+ "active": 1197
+ },
+ "Graduate Collection": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Graduate Collection",
+ "match": "exact",
+ "products": 50,
+ "active": 49
+ },
+ "Graduate Collection UK": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Graduate Collection",
+ "match": "suffix-strip",
+ "products": 37,
+ "active": 35
+ },
+ "Graham & Brown": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "graham_brown_catalog",
+ "backing": "Graham & Brown",
+ "match": "exact",
+ "products": 1679,
+ "active": 405
+ },
+ "Grasscloth": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Grasscloth",
+ "match": "exact",
+ "products": 3,
+ "active": 0
+ },
+ "Grasscloth Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Grasscloth",
+ "match": "suffix-strip",
+ "products": 1,
+ "active": 0
+ },
+ "Hand Crafted": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 162,
+ "active": 40
+ },
+ "Happy Menocal": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Happy Menocal",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Harlequin": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "harlequin_catalog",
+ "backing": "Harlequin",
+ "match": "exact",
+ "products": 586,
+ "active": 583
+ },
+ "Heritage Collection": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "Hermes": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "hermes_catalog",
+ "backing": "Hermes",
+ "match": "exact",
+ "products": 29,
+ "active": 0
+ },
+ "Hinson": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 2,
+ "active": 0
+ },
+ "Holland and Sherry": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": null,
+ "backing": "Holland and Sherry",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Holly Hunt": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "holly_hunt_catalog",
+ "backing": "Holly Hunt",
+ "match": "exact",
+ "products": 1,
+ "active": 0
+ },
+ "Holly Hunt In Stock": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "Holly Hunt Walls": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "holly_hunt_catalog",
+ "backing": "Holly Hunt",
+ "match": "suffix-strip",
+ "products": 1257,
+ "active": 0
+ },
+ "Hollywood Acoustical": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 63,
+ "active": 13
+ },
+ "Hollywood Wallcoverings": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "hollywood_catalog",
+ "backing": "Hollywood Wallcoverings",
+ "match": "exact",
+ "products": 5640,
+ "active": 3155
+ },
+ "Home Couture": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Home Couture",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Hospitality Wallcoverings": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 98,
+ "active": 96
+ },
+ "Hygge & West": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": true,
+ "adapter": "shopify-public",
+ "reason": "public Shopify storefront stock (.js feed)",
+ "catalog_table": "hygge_catalog",
+ "backing": "Hygge & West",
+ "match": "exact",
+ "products": 11,
+ "active": 10
+ },
+ "IKSEL": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": null,
+ "backing": "IKSEL",
+ "match": "exact",
+ "products": 88,
+ "active": 0
+ },
+ "Innovations": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "innovations_catalog",
+ "backing": "Innovations",
+ "match": "exact",
+ "products": 9,
+ "active": 8
+ },
+ "Innovations USA": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "innovations_catalog",
+ "backing": "Innovations",
+ "match": "suffix-strip",
+ "products": 471,
+ "active": 210
+ },
+ "Jane Churchill": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 202,
+ "active": 0
+ },
+ "Jeffrey Stevens": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "jeffrey_stevens_catalog",
+ "backing": "York (Jeffrey Stevens source)",
+ "match": "private-label",
+ "products": 3809,
+ "active": 1498
+ },
+ "JF Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "jf_fabrics_catalog",
+ "backing": "JF Fabrics",
+ "match": "exact",
+ "products": 2643,
+ "active": 0
+ },
+ "JF FABRICS at DW": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 3240,
+ "active": 0
+ },
+ "Kelly Wearstler": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "vendor_catalog",
+ "backing": "Kelly Wearstler",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Kirkby Design": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "kirkby_catalog",
+ "backing": "Kirkby Design",
+ "match": "exact",
+ "products": 3,
+ "active": 2
+ },
+ "Koroseal": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "koroseal_catalog",
+ "backing": "Koroseal",
+ "match": "exact",
+ "products": 2548,
+ "active": 2351
+ },
+ "Kravet": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "kravet_catalog",
+ "backing": "Kravet",
+ "match": "exact",
+ "products": 4902,
+ "active": 2227
+ },
+ "Kravet Couture": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 4,
+ "active": 2
+ },
+ "Kravet Design": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 4,
+ "active": 2
+ },
+ "LA Walls": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "la_walls_catalog",
+ "backing": "LA Walls",
+ "match": "exact",
+ "products": 728,
+ "active": 535
+ },
+ "Larsen": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 65,
+ "active": 0
+ },
+ "Laura Ashley Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "laura_ashley_catalog",
+ "backing": "Laura Ashley",
+ "match": "suffix-strip",
+ "products": 158,
+ "active": 110
+ },
+ "Lee Jofa": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "lee_jofa_catalog",
+ "backing": "Lee Jofa",
+ "match": "exact",
+ "products": 3695,
+ "active": 2152
+ },
+ "Lee Jofa Modern": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 2,
+ "active": 1
+ },
+ "LEED Walls": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "leed_walls_catalog",
+ "backing": "LEED Walls",
+ "match": "exact",
+ "products": 129,
+ "active": 75
+ },
+ "Limited Stock": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 122,
+ "active": 0
+ },
+ "Limited Stock Flock": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 4,
+ "active": 0
+ },
+ "Limited Stock Flocked": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 60,
+ "active": 0
+ },
+ "Limited Stock Prints": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 60,
+ "active": 0
+ },
+ "Lincrusta": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": false,
+ "adapter": "woo-public",
+ "reason": "WooCommerce stock adapter ready — pending per-site verification",
+ "catalog_table": "lincrusta_catalog",
+ "backing": "Lincrusta",
+ "match": "exact",
+ "products": 96,
+ "active": 47
+ },
+ "Linherr Hollingsworth": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Linherr Hollingsworth",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Los Angeles Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 2366,
+ "active": 1840
+ },
+ "Luxury Murals": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 56,
+ "active": 56
+ },
+ "Madagascar Walls": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 68,
+ "active": 49
+ },
+ "Malibu": {
+ "tier": "PORTAL_CREDS",
+ "live_capable": true,
+ "adapter": "wallquest",
+ "reason": "WallQuest trade portal (creds on file)",
+ "catalog_table": "wallquest_catalog",
+ "backing": null,
+ "match": "unmatched",
+ "products": 3,
+ "active": 3
+ },
+ "Malibu Wallpaper": {
+ "tier": "PORTAL_CREDS",
+ "live_capable": true,
+ "adapter": "wallquest",
+ "reason": "WallQuest trade portal (creds on file)",
+ "catalog_table": "wallquest_catalog",
+ "backing": "Malibu Wallpaper",
+ "match": "exact",
+ "products": 4031,
+ "active": 2596
+ },
+ "Malibu Walls": {
+ "tier": "PORTAL_CREDS",
+ "live_capable": true,
+ "adapter": "wallquest",
+ "reason": "WallQuest trade portal (creds on file)",
+ "catalog_table": "wallquest_catalog",
+ "backing": null,
+ "match": "unmatched",
+ "products": 119,
+ "active": 1
+ },
+ "Manuel Canovas": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "manuel_canovas_catalog",
+ "backing": "Manuel Canovas",
+ "match": "exact",
+ "products": 195,
+ "active": 0
+ },
+ "Marburg": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "marburg_catalog",
+ "backing": "Marburg",
+ "match": "exact",
+ "products": 121,
+ "active": 112
+ },
+ "Marimekko Exclusive": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 36,
+ "active": 35
+ },
+ "Mark Alexander": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "mark_alexander_catalog",
+ "backing": "Mark Alexander",
+ "match": "exact",
+ "products": 2,
+ "active": 1
+ },
+ "Martyn Lawrence Bullard": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 77,
+ "active": 0
+ },
+ "Maya Romanoff": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "maya_catalog",
+ "backing": "Maya Romanoff",
+ "match": "exact",
+ "products": 690,
+ "active": 624
+ },
+ "MC Escher Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "MC Escher",
+ "match": "suffix-strip",
+ "products": 50,
+ "active": 50
+ },
+ "Mid Century Modern": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 112,
+ "active": 106
+ },
+ "Milton & King": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": false,
+ "adapter": "woo-public",
+ "reason": "WooCommerce stock adapter ready — pending per-site verification",
+ "catalog_table": "milton_king_catalog",
+ "backing": "Milton & King",
+ "match": "exact",
+ "products": 2,
+ "active": 1
+ },
+ "Mind the Gap": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "mindthegap_catalog",
+ "backing": "Mind the Gap",
+ "match": "exact",
+ "products": 1261,
+ "active": 1134
+ },
+ "Missoni Fabric": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "missoni_catalog",
+ "backing": "Missoni",
+ "match": "suffix-strip",
+ "products": 2,
+ "active": 0
+ },
+ "Missoni Home": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "missoni_catalog",
+ "backing": "Missoni",
+ "match": "suffix-strip",
+ "products": 5,
+ "active": 0
+ },
+ "Missoni Wallpaper": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "missoni_catalog",
+ "backing": "Missoni",
+ "match": "suffix-strip",
+ "products": 119,
+ "active": 57
+ },
+ "Morris and Company": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": null,
+ "backing": "Morris and Company",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Mulberry": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "mulberry_catalog",
+ "backing": "Mulberry",
+ "match": "exact",
+ "products": 484,
+ "active": 319
+ },
+ "Natural Paint": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 26,
+ "active": 26
+ },
+ "Newmor": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": false,
+ "adapter": "woo-public",
+ "reason": "WooCommerce stock adapter ready — pending per-site verification",
+ "catalog_table": "newmor_catalog",
+ "backing": "Newmor",
+ "match": "exact",
+ "products": 1,
+ "active": 0
+ },
+ "Newmor Wallcoverings": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": false,
+ "adapter": "woo-public",
+ "reason": "WooCommerce stock adapter ready — pending per-site verification",
+ "catalog_table": "newmor_catalog",
+ "backing": "Newmor",
+ "match": "suffix-strip",
+ "products": 542,
+ "active": 515
+ },
+ "Nina Campbell": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": true,
+ "adapter": "shopify-public",
+ "reason": "public Shopify storefront stock (.js feed)",
+ "catalog_table": "nina_campbell_catalog",
+ "backing": "Nina Campbell",
+ "match": "exact",
+ "products": 791,
+ "active": 551
+ },
+ "Nina Campbell Wallcoverings": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": true,
+ "adapter": "shopify-public",
+ "reason": "public Shopify storefront stock (.js feed)",
+ "catalog_table": "nina_campbell_catalog",
+ "backing": "Nina Campbell",
+ "match": "suffix-strip",
+ "products": 111,
+ "active": 0
+ },
+ "NLXL": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": true,
+ "adapter": "shopify-public",
+ "reason": "public Shopify storefront stock (.js feed)",
+ "catalog_table": "nlxl_catalog",
+ "backing": "NLXL",
+ "match": "exact",
+ "products": 10,
+ "active": 9
+ },
+ "Nobilis": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "nobilis_catalog",
+ "backing": "Nobilis",
+ "match": "exact",
+ "products": 179,
+ "active": 75
+ },
+ "Novasuede": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "novasuede_catalog",
+ "backing": "Novasuede",
+ "match": "exact",
+ "products": 196,
+ "active": 157
+ },
+ "OLIVIA AND POPP": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Olivia and Popp",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Osborne & Little": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "osborne_catalog",
+ "backing": "Osborne & Little",
+ "match": "exact",
+ "products": 1041,
+ "active": 957
+ },
+ "Osborne & Little Fabrics": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "osborne_catalog",
+ "backing": "Osborne & Little",
+ "match": "suffix-strip",
+ "products": 1101,
+ "active": 0
+ },
+ "Parkertex": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 29,
+ "active": 0
+ },
+ "Patty Madden": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Patty Madden",
+ "match": "exact",
+ "products": 2,
+ "active": 2
+ },
+ "Paul Montgomery": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "paul_montgomery_catalog",
+ "backing": "Paul Montgomery",
+ "match": "exact",
+ "products": 656,
+ "active": 0
+ },
+ "Paul Montgomery Art Prints": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 397,
+ "active": 0
+ },
+ "Paul Montgomery Original Art": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 49,
+ "active": 0
+ },
+ "Paul Montgomery Studios": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "paul_montgomery_catalog",
+ "backing": "Paul Montgomery",
+ "match": "suffix-strip",
+ "products": 443,
+ "active": 0
+ },
+ "Peel and Stick": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 92,
+ "active": 0
+ },
+ "Peg Norriss": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Peg Norriss",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Phillip Jeffries": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "pj_catalog",
+ "backing": "Phillip Jeffries",
+ "match": "exact",
+ "products": 3087,
+ "active": 2473
+ },
+ "Phillipe Romano": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "astek_catalog",
+ "backing": "Astek",
+ "match": "private-label",
+ "products": 18919,
+ "active": 10136
+ },
+ "Phyllis Morris": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 28,
+ "active": 27
+ },
+ "Pierre Frey": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "pierre_frey_catalog",
+ "backing": "Pierre Frey",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Pixels": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Pixels",
+ "match": "exact",
+ "products": 59,
+ "active": 59
+ },
+ "Plains": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Plains",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Porsche™ Paint - Speed Yellow": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "PR Faux Leather": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 418,
+ "active": 327
+ },
+ "Primo Leathers": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "primo_leathers_catalog",
+ "backing": "Primo Leathers",
+ "match": "exact",
+ "products": 135,
+ "active": 109
+ },
+ "Printy6": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Printy6",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "PS Removable Wallpaper": {
+ "tier": "PORTAL_CREDS",
+ "live_capable": true,
+ "adapter": "wallquest",
+ "reason": "WallQuest trade portal (creds on file)",
+ "catalog_table": "wallquest_catalog",
+ "backing": null,
+ "match": "unmatched",
+ "products": 737,
+ "active": 736
+ },
+ "Quadrille": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Quadrille",
+ "match": "exact",
+ "products": 9,
+ "active": 9
+ },
+ "Ralph Lauren": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "rl_catalog",
+ "backing": "Ralph Lauren",
+ "match": "exact",
+ "products": 460,
+ "active": 142
+ },
+ "Ralph Lauren Fabric": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "rl_catalog",
+ "backing": "Ralph Lauren",
+ "match": "suffix-strip",
+ "products": 1742,
+ "active": 0
+ },
+ "Ralph Lauren Fabrics": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "rl_catalog",
+ "backing": "Ralph Lauren",
+ "match": "suffix-strip",
+ "products": 6,
+ "active": 0
+ },
+ "Ralph Lauren Wallpaper": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "rl_catalog",
+ "backing": "Ralph Lauren",
+ "match": "suffix-strip",
+ "products": 316,
+ "active": 0
+ },
+ "Rebecca Moses": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 1
+ },
+ "Rebel Studio": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Rebel Studio",
+ "match": "exact",
+ "products": 2,
+ "active": 1
+ },
+ "Rebel Walls": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "rebelwalls_catalog",
+ "backing": "Rebel Walls",
+ "match": "exact",
+ "products": 3721,
+ "active": 3613
+ },
+ "Retro Walls": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1073,
+ "active": 63
+ },
+ "Roberto Cavalli": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "roberto_cavalli_catalog",
+ "backing": "Roberto Cavalli",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Roberto Cavalli Wallpaper": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "roberto_cavalli_catalog",
+ "backing": "Roberto Cavalli",
+ "match": "suffix-strip",
+ "products": 180,
+ "active": 149
+ },
+ "Romo": {
+ "tier": "PORTAL_CREDS",
+ "live_capable": true,
+ "adapter": "romo",
+ "reason": "Romo trade portal (creds on file)",
+ "catalog_table": "romo_catalog",
+ "backing": "Romo",
+ "match": "exact",
+ "products": 568,
+ "active": 521
+ },
+ "Ronald Redding": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 732,
+ "active": 211
+ },
+ "Sacha Walckhoff": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Sacha Walckhoff",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Sancar": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": true,
+ "adapter": "shopify-public",
+ "reason": "public Shopify storefront stock (.js feed)",
+ "catalog_table": "sancar_catalog",
+ "backing": "Sancar",
+ "match": "exact",
+ "products": 42,
+ "active": 42
+ },
+ "Sandberg": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "sandberg_catalog",
+ "backing": "Sandberg",
+ "match": "exact",
+ "products": 991,
+ "active": 769
+ },
+ "Sara Bergqvist": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Sara Bergqvist",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Sarah Bartholomew": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Sarah Bartholomew",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Scalamandre": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "scalamandre_catalog",
+ "backing": "Scalamandre",
+ "match": "exact",
+ "products": 1280,
+ "active": 418
+ },
+ "Scalamandre Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "scalamandre_catalog",
+ "backing": "Scalamandre",
+ "match": "suffix-strip",
+ "products": 10178,
+ "active": 1
+ },
+ "Scalamandre Wallpaper": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "scalamandre_catalog",
+ "backing": "Scalamandre",
+ "match": "suffix-strip",
+ "products": 1153,
+ "active": 966
+ },
+ "Schumacher": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "schumacher_catalog",
+ "backing": "Schumacher",
+ "match": "exact",
+ "products": 5180,
+ "active": 2340
+ },
+ "Schumacher Fabrics": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "schumacher_catalog",
+ "backing": "Schumacher",
+ "match": "suffix-strip",
+ "products": 4802,
+ "active": 0
+ },
+ "Schumacher Pillows": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "schumacher_catalog",
+ "backing": "Schumacher",
+ "match": "suffix-strip",
+ "products": 17,
+ "active": 0
+ },
+ "Schumacher Trim": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "schumacher_catalog",
+ "backing": "Schumacher",
+ "match": "suffix-strip",
+ "products": 1174,
+ "active": 0
+ },
+ "Schumacher USA": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "schumacher_catalog",
+ "backing": "Schumacher",
+ "match": "suffix-strip",
+ "products": 343,
+ "active": 0
+ },
+ "Schumacher Wallcoverings": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "schumacher_catalog",
+ "backing": "Schumacher",
+ "match": "suffix-strip",
+ "products": 1,
+ "active": 0
+ },
+ "Schumacher Wallpaper": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "schumacher_catalog",
+ "backing": "Schumacher",
+ "match": "suffix-strip",
+ "products": 2057,
+ "active": 0
+ },
+ "Scion": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 2,
+ "active": 1
+ },
+ "Showroom Line": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 43,
+ "active": 11
+ },
+ "Sir Edward": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 31,
+ "active": 0
+ },
+ "Sister Parish": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "sisterparish_catalog",
+ "backing": "Sister Parish",
+ "match": "exact",
+ "products": 72,
+ "active": 72
+ },
+ "Steve Abrams Studios": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 55,
+ "active": 51
+ },
+ "Steven Abrams Photography": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 1
+ },
+ "Studio Ditte": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Studio Ditte",
+ "match": "exact",
+ "products": 1,
+ "active": 1
+ },
+ "Studio Printworks": {
+ "tier": "PUBLIC_STOCK",
+ "live_capable": true,
+ "adapter": "shopify-public",
+ "reason": "public Shopify storefront stock (.js feed)",
+ "catalog_table": "studio_printworks_catalog",
+ "backing": "Studio Printworks",
+ "match": "exact",
+ "products": 1,
+ "active": 0
+ },
+ "SUGARBOO": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 10,
+ "active": 10
+ },
+ "Suncloth": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "quadrille_house_catalog",
+ "backing": "Suncloth",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Surface Stick": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "surface_stick_catalog",
+ "backing": "Surface Stick",
+ "match": "exact",
+ "products": 751,
+ "active": 743
+ },
+ "Telefina Fine Fabrics": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 64,
+ "active": 0
+ },
+ "TEST": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 5,
+ "active": 0
+ },
+ "The Set Decorator": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "Thibaut": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "thibaut_catalog",
+ "backing": "Thibaut",
+ "match": "exact",
+ "products": 3874,
+ "active": 2052
+ },
+ "Threads": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "threads_catalog",
+ "backing": "Threads",
+ "match": "exact",
+ "products": 81,
+ "active": 71
+ },
+ "Timorous Beasties": {
+ "tier": "PORTAL_NO_CREDS",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor portal exists but no trade credentials on file — supply creds to enable",
+ "catalog_table": "timorous_catalog",
+ "backing": "Timorous Beasties",
+ "match": "exact",
+ "products": 2,
+ "active": 0
+ },
+ "Traditional Whimsy": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 214,
+ "active": 90
+ },
+ "Tres Tintas": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "tres_tintas_catalog",
+ "backing": "Tres Tintas",
+ "match": "exact",
+ "products": 577,
+ "active": 577
+ },
+ "Trikes-DL Couch-Eykon-Source-One": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 1,
+ "active": 0
+ },
+ "Trikes-DL Couch-Eykon-Tower": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 808,
+ "active": 0
+ },
+ "TWIL": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line (private-label aggregate or unmapped)",
+ "catalog_table": null,
+ "backing": null,
+ "match": "unmatched",
+ "products": 190,
+ "active": 0
+ },
+ "Ultrasuede": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "ultrasuede_catalog",
+ "backing": "Ultrasuede",
+ "match": "exact",
+ "products": 111,
+ "active": 108
+ },
+ "Vahallan": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Vahallan",
+ "match": "exact",
+ "products": 4,
+ "active": 4
+ },
+ "Versa Designed Surfaces": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "versa_catalog",
+ "backing": "Versa Designed Surfaces",
+ "match": "exact",
+ "products": 884,
+ "active": 842
+ },
+ "Versace": {
+ "tier": "QUOTE_ONLY",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "vendor does not publish live stock (to-the-trade / quote-only)",
+ "catalog_table": "versace_catalog",
+ "backing": "Versace",
+ "match": "exact",
+ "products": 542,
+ "active": 472
+ },
+ "Villa Nova": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "villa_nova_catalog",
+ "backing": "Villa Nova",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Wallpaper NYC": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Wallpaper NYC",
+ "match": "exact",
+ "products": 95,
+ "active": 12
+ },
+ "William Morris": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "william_morris_catalog",
+ "backing": "William Morris",
+ "match": "exact",
+ "products": 533,
+ "active": 526
+ },
+ "Winfield Thybony": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Winfield Thybony",
+ "match": "exact",
+ "products": 3,
+ "active": 2
+ },
+ "Witch & Watchman": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "vendor_catalog",
+ "backing": "Witch & Watchman",
+ "match": "exact",
+ "products": 10,
+ "active": 10
+ },
+ "Wolf Gordon": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "wolf_gordon_catalog",
+ "backing": "Wolf Gordon",
+ "match": "exact",
+ "products": 1527,
+ "active": 688
+ },
+ "Zeuxis Parrhasius at DW": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": null,
+ "backing": "Zeuxis Parrhasius",
+ "match": "suffix-strip",
+ "products": 5,
+ "active": 5
+ },
+ "Zeuxis Parrhasius Europe": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": null,
+ "backing": "Zeuxis Parrhasius",
+ "match": "suffix-strip",
+ "products": 32,
+ "active": 22
+ },
+ "Zinc Textile": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "zinc_catalog",
+ "backing": "Zinc Textile",
+ "match": "exact",
+ "products": 3,
+ "active": 3
+ },
+ "Zoffany": {
+ "tier": "NO_STOCK",
+ "live_capable": false,
+ "adapter": null,
+ "reason": "no live stock source identified for this line",
+ "catalog_table": "zoffany_catalog",
+ "backing": "Zoffany",
+ "match": "exact",
+ "products": 358,
+ "active": 322
+ }
+ }
+}
\ No newline at end of file
diff --git a/scripts/build-coverage.js b/scripts/build-coverage.js
new file mode 100644
index 0000000..8ce7486
--- /dev/null
+++ b/scripts/build-coverage.js
@@ -0,0 +1,217 @@
+#!/usr/bin/env node
+// build-coverage.js — the LIVE-STOCK COVERAGE AUDIT generator for all.designerwallcoverings.com.
+//
+// Classifies EVERY display-vendor in the grid into a feasibility tier and writes the
+// committed source-of-truth at data/live-stock-coverage.json. The server reads that file
+// to drive each card's "Check Live" enable/dim (data-driven, not hardcoded per vendor),
+// and the live worker reads the per-vendor `adapter` + `catalog_table` to route a scrape.
+//
+// Tiers (Steve's audit spec):
+// PORTAL_CREDS — backing vendor has a login portal AND trade creds on file → live-capable (metered).
+// PUBLIC_STOCK — backing storefront exposes stock with no login (Shopify .js / Woo Store API) → live-capable (metered headless).
+// PORTAL_NO_CREDS — a portal exists but no creds → NOT live yet (needs creds); dims with that reason.
+// QUOTE_ONLY — to-the-trade / quote-only line that publishes no stock anywhere → NOT feasible; always dims.
+// NO_STOCK — no live stock source identified (private-label aggregate, one-off, internal) → dims.
+//
+// $0 (local) — pure Postgres reads, no paid API.
+//
+// node scripts/build-coverage.js # write data/live-stock-coverage.json
+// node scripts/build-coverage.js --dry # print summary, don't write
+const fs = require('fs');
+const path = require('path');
+const { Pool } = require('pg');
+try { require('dotenv').config({ path: path.join(__dirname, '..', '.env') }); } catch {}
+
+const DSN = process.env.DATABASE_URL || 'postgresql:///dw_unified?host=/tmp';
+const OUT = path.join(__dirname, '..', 'data', 'live-stock-coverage.json');
+const DRY = process.argv.includes('--dry');
+
+// Mirror server.js's public-facing exclusion — banned upstream/private-label source names
+// never surface on the public grid, so they are not display-vendors we classify.
+const BANNED = /brewster|york|wallquest|wall\s*quest|newwall|new\s*wall\b|command\s*54|justin\s*david|nicolette\s*mayer|seabrook|chesapeake|nextwall|desima|carlsten/i;
+
+const norm = (s) => String(s || '').trim().toLowerCase().replace(/[.\s]+$/, '');
+// suffixes that distinguish a display-vendor variant from its registry parent
+const SUFFIX = /\s+(fabrics?|wallpapers?|wallcoverings?|walls?|trim|pillows?|murals?|at dw|europe|usa|uk|to go|home|studios?)$/i;
+const stripSuffix = (s) => { let p = String(s || ''); for (let i = 0; i < 3; i++) { const n = p.replace(SUFFIX, ''); if (n === p) break; p = n; } return p.trim(); };
+
+// Platform is detected from the catalog's PRODUCT_URL pattern, NOT vendor_registry.website_tech_stack
+// (that field is ~70% blank/wrong — hygge is tagged "unreachable" yet is a live public Shopify store).
+// CANONICAL Shopify storefront product URL = host/products/<single-handle> (exactly one segment after
+// /products/, so it exposes a public <url>.js stock feed). Thibaut's /products/wallcoverings/<code> has
+// TWO segments → login-gated, correctly excluded. Our own storefront is excluded (circular).
+const CANONICAL_SHOPIFY = /^https?:\/\/([^/]+)\/products\/[^/?#]+\/?(?:[?#].*)?$/i;
+const isCanonicalShopify = (url) => { const m = CANONICAL_SHOPIFY.exec(String(url || '')); return !!m && !/designerwallcoverings\.com/i.test(m[1]); };
+// WooCommerce single-product URL = host/product/<slug> (singular) → /wp-json/wc/store/products?slug=
+const WOO_URL = /^https?:\/\/[^/]+\/product\/[^/?#]+/i;
+// display-vendor labels that are WallQuest-backed but don't resolve through vendor_registry
+// (the private-label names the grid shows; SKUs live in wallquest_catalog).
+const WALLQUEST_ALIASES = new Set(['malibu wallpaper', 'ps removable wallpaper', 'malibu walls', 'malibu']);
+
+// Known to-the-trade / quote-only houses that publish NO stock anywhere (memory + DW knowledge).
+// A matched vendor here is QUOTE_ONLY regardless of a marketing site existing.
+const QUOTE_ONLY = new Set([
+ 'dedar', 'de gournay', 'de gournay murals', 'fromental', 'gracie', 'iksel', 'zuber',
+ 'porter teleo', 'holland and sherry', 'holland & sherry', 'clarence house', 'fortuny',
+ 'fortuny fabrics', 'pierre frey', 'manuel canovas', 'jim thompson', 'jim thompson fabrics',
+ 'nobilis', 'elitis', 'maya romanoff', 'donghia', 'hermes', 'armani casa', 'armani/casa',
+ 'dolce & gabbana', 'dolce and gabbana', 'versace', 'roberto cavalli', 'roberto cavalli wallpaper',
+ 'christian lacroix europe', 'missoni home', 'missoni wallpaper', 'missoni fabric',
+ 'kelly wearstler', 'martyn lawrence bullard', 'celerie kemble', 'sister parish',
+ 'holly hunt', 'holly hunt walls', 'holly hunt in stock', 'quadrille', 'china seas',
+ 'alan campbell', 'home couture', 'cloth and paper', 'charles burger', 'grasscloth',
+]);
+
+async function main() {
+ const pool = new Pool({ connectionString: DSN, max: 2 });
+
+ // 1. distinct display-vendors from the grid (same filter the server applies)
+ const { rows: vRows } = await pool.query(
+ `SELECT vendor, count(*)::int AS total,
+ count(*) FILTER (WHERE upper(coalesce(status,''))='ACTIVE')::int AS active
+ FROM shopify_products
+ WHERE coalesce(status,'') <> 'DELETED_FROM_SHOPIFY' AND vendor IS NOT NULL AND vendor <> ''
+ GROUP BY vendor`);
+ const displayVendors = vRows.filter((r) => !BANNED.test(r.vendor));
+
+ // 2. vendor_registry — the credential + portal + platform truth
+ const { rows: reg } = await pool.query(
+ `SELECT vendor_name, vendor_code, coalesce(private_label_name,'') AS private_label_name,
+ coalesce(catalog_table,'') AS catalog_table, coalesce(login_url,'') AS login_url,
+ (trade_password IS NOT NULL AND trade_password <> '') AS has_pass,
+ lower(coalesce(website_tech_stack,'')) AS stack,
+ coalesce(website_url,'') AS website_url,
+ display_prices
+ FROM vendor_registry`);
+
+ // 3. per catalog table: does it carry resolvable product_urls, and what PLATFORM are they?
+ // (sampled from the URLs themselves — the reliable signal, vs the broken tech_stack field.)
+ const { rows: urlTabs } = await pool.query(
+ `SELECT c.table_name FROM information_schema.columns c
+ WHERE c.table_schema='public' AND c.column_name='product_url'
+ AND (c.table_name ~ '_catalog$' OR c.table_name ~ '^catalog_')`);
+ const catUrlCount = new Map(), catShopify = new Map(), catWoo = new Map();
+ for (const { table_name } of urlTabs) {
+ try {
+ const { rows } = await pool.query(
+ `SELECT product_url FROM "${table_name}" WHERE product_url IS NOT NULL AND product_url <> '' LIMIT 40`);
+ catUrlCount.set(table_name, rows.length);
+ const shop = rows.filter((r) => isCanonicalShopify(r.product_url)).length;
+ const woo = rows.filter((r) => WOO_URL.test(r.product_url)).length;
+ // majority-of-sample vote so one odd URL doesn't flip the platform
+ catShopify.set(table_name, rows.length > 0 && shop >= Math.max(1, rows.length * 0.5));
+ catWoo.set(table_name, rows.length > 0 && woo >= Math.max(1, rows.length * 0.5));
+ } catch { /* skip unreadable */ }
+ }
+ const hasUrls = (tbl) => tbl && (catUrlCount.get(tbl) || 0) > 0;
+ // shared bucket table is NOT per-SKU resolvable for a single vendor's live URL
+ const dedicated = (tbl) => tbl && tbl !== 'vendor_catalog';
+
+ // registry lookup indexes
+ const byName = new Map(); // lower(vendor_name) → row
+ const byPrivateLabel = new Map(); // lower(private_label_name) → [rows]
+ for (const r of reg) {
+ byName.set(norm(r.vendor_name), r);
+ if (r.private_label_name) (byPrivateLabel.get(norm(r.private_label_name)) || byPrivateLabel.set(norm(r.private_label_name), []).get(norm(r.private_label_name))).push(r);
+ }
+ // resolve a display-vendor → best backing registry row (+ how it matched)
+ function resolve(vendor) {
+ const v = norm(vendor);
+ if (byName.has(v)) return { row: byName.get(v), method: 'exact' };
+ // display name IS a private-label bucket → pick the strongest backing (creds > shopify > first)
+ if (byPrivateLabel.has(v)) {
+ const rows = byPrivateLabel.get(v);
+ const pick = rows.find((r) => r.has_pass) || rows.find((r) => catShopify.get(r.catalog_table)) || rows[0];
+ return { row: pick, method: 'private-label' };
+ }
+ const s = norm(stripSuffix(vendor));
+ if (s !== v && byName.has(s)) return { row: byName.get(s), method: 'suffix-strip' };
+ return { row: null, method: 'unmatched' };
+ }
+
+ // adapter routing (only the reliable-contract adapters ENABLE; Woo is wired-but-dimmed)
+ function classify(vendor, backing, method) {
+ const v = norm(vendor);
+ // A private-label BUCKET (e.g. "Phillipe Romano" = Astek + Command54 + Justin David) aggregates
+ // many upstreams — a single backing catalog can't represent it, so a public-stock scrape would
+ // mostly mis-route and could associate the private label with a real vendor's site. Only 1:1
+ // matches (exact / suffix-strip) earn a public-stock adapter; buckets stay dim unless WallQuest-backed.
+ const oneToOne = method === 'exact' || method === 'suffix-strip';
+ // 0. WallQuest-backed private labels that don't resolve through vendor_registry — the grid
+ // shows the private-label name; SKUs live in wallquest_catalog (the adapter looks them up).
+ if (WALLQUEST_ALIASES.has(v))
+ return { tier: 'PORTAL_CREDS', live_capable: true, adapter: 'wallquest',
+ reason: 'WallQuest trade portal (creds on file)', catalog_table: 'wallquest_catalog' };
+ if (QUOTE_ONLY.has(v)) return { tier: 'QUOTE_ONLY', live_capable: false, adapter: null,
+ reason: 'vendor does not publish live stock (to-the-trade / quote-only)' };
+ if (!backing) return { tier: 'NO_STOCK', live_capable: false, adapter: null,
+ reason: 'no live stock source identified for this line (private-label aggregate or unmapped)' };
+
+ const tbl = backing.catalog_table || '', pl = norm(backing.private_label_name);
+ const isWQ = /^(wallquest|malibu|brewster)_catalog$/.test(tbl) || pl === 'malibu wallpaper';
+ const isRomo = norm(backing.vendor_code) === 'romo' || norm(backing.vendor_name) === 'romo';
+ // 1. PORTAL+CREDS — wired portal adapters. WallQuest resolves via wallquest_catalog regardless of
+ // which sister row (brewster/malibu) mapped; Romo logs into trade.theromogroup.com.
+ if (isWQ)
+ return { tier: 'PORTAL_CREDS', live_capable: true, adapter: 'wallquest',
+ reason: 'WallQuest trade portal (creds on file)', catalog_table: 'wallquest_catalog' };
+ if (isRomo && hasUrls(tbl))
+ return { tier: 'PORTAL_CREDS', live_capable: true, adapter: 'romo',
+ reason: 'Romo trade portal (creds on file)', catalog_table: tbl || 'romo_catalog' };
+ // 2. PUBLIC_STOCK (Shopify) — canonical public .js feed, dedicated catalog, no login → ENABLE.
+ // Precedes the portal check: a login_url may exist (an account page) yet stock is public.
+ if (oneToOne && dedicated(tbl) && hasUrls(tbl) && catShopify.get(tbl))
+ return { tier: 'PUBLIC_STOCK', live_capable: true, adapter: 'shopify-public',
+ reason: 'public Shopify storefront stock (.js feed)', catalog_table: tbl };
+ if (backing.has_pass) // creds exist but no adapter wired for this specific portal yet
+ return { tier: 'PORTAL_CREDS', live_capable: false, adapter: null,
+ reason: 'backing portal has trade creds but no live adapter wired yet', catalog_table: tbl };
+ // 3. PORTAL+NO-CREDS — a login portal exists but no creds (Magento/B2B hide stock) → needs creds
+ if (backing.login_url)
+ return { tier: 'PORTAL_NO_CREDS', live_capable: false, adapter: null,
+ reason: 'vendor portal exists but no trade credentials on file — supply creds to enable', catalog_table: tbl };
+ // 4. PUBLIC_STOCK (Woo) — WooCommerce Store API; adapter wired but not per-site verified → dim
+ if (oneToOne && dedicated(tbl) && hasUrls(tbl) && catWoo.get(tbl))
+ return { tier: 'PUBLIC_STOCK', live_capable: false, adapter: 'woo-public',
+ reason: 'WooCommerce stock adapter ready — pending per-site verification', catalog_table: tbl };
+ // 5. explicit quote-only signal from registry
+ if (backing.display_prices === false)
+ return { tier: 'QUOTE_ONLY', live_capable: false, adapter: null,
+ reason: 'vendor does not publish live stock (to-the-trade / quote-only)' };
+ return { tier: 'NO_STOCK', live_capable: false, adapter: null,
+ reason: 'no live stock source identified for this line' };
+ }
+
+ const vendors = {};
+ const counts = { PORTAL_CREDS: 0, PUBLIC_STOCK: 0, PORTAL_NO_CREDS: 0, QUOTE_ONLY: 0, NO_STOCK: 0, live_capable: 0 };
+ for (const dv of displayVendors) {
+ const { row: backing, method } = resolve(dv.vendor);
+ const c = classify(dv.vendor, backing, method);
+ vendors[dv.vendor] = {
+ tier: c.tier, live_capable: c.live_capable, adapter: c.adapter || null, reason: c.reason,
+ catalog_table: c.catalog_table || (backing && backing.catalog_table) || null,
+ backing: backing ? backing.vendor_name : null, match: method,
+ products: dv.total, active: dv.active,
+ };
+ counts[c.tier] = (counts[c.tier] || 0) + 1;
+ if (c.live_capable) counts.live_capable += 1;
+ }
+
+ const out = {
+ generated_at: new Date().toISOString(),
+ generator: 'scripts/build-coverage.js',
+ total_display_vendors: displayVendors.length,
+ counts,
+ // vendors keyed by the exact display-vendor string the grid uses (case-sensitive)
+ vendors,
+ };
+ await pool.end();
+
+ if (DRY) { console.log(JSON.stringify({ counts, total: out.total_display_vendors }, null, 2)); return; }
+ fs.writeFileSync(OUT, JSON.stringify(out, null, 2));
+ console.log(`coverage → ${OUT}`);
+ console.log(` ${out.total_display_vendors} display-vendors | live-capable ${counts.live_capable}`);
+ console.log(` PORTAL_CREDS ${counts.PORTAL_CREDS} · PUBLIC_STOCK ${counts.PUBLIC_STOCK} · PORTAL_NO_CREDS ${counts.PORTAL_NO_CREDS} · QUOTE_ONLY ${counts.QUOTE_ONLY} · NO_STOCK ${counts.NO_STOCK}`);
+}
+
+main().catch((e) => { console.error('coverage build failed:', e.message); process.exit(1); });
← 8c24b22 all-dw: show Mfr # (mfr_sku) + Mfr Name (supplier_name) as c
·
back to All Designerwallcoverings
·
live-stock adapter framework: generalized per-vendor registr af39b75 →