← back to Tk11438 Postgres Migration

verification/tk11517-domain/directory-review.json

201 lines

{
  "ticket": "TK-11517-serve-authenticated-gracie-internal-doma",
  "status": "complete-read-only-review",
  "reviewed_at": "2026-09-11T20:44:19.132920+00:00",
  "source_root": "/Users/macstudio3/Projects/all-designerwallcoverings",
  "artifact_only_mutation": true,
  "changes": [],
  "scope": "Local source and existing JSON snapshots only; no crawler, app restart, remote request, DB query or send.",
  "directory": {
    "ui_url": "https://all.designerwallcoverings.com/microsites.html",
    "api_url": "https://all.designerwallcoverings.com/api/microsites",
    "ui_entrypoint": "public/index.html:303 microsites link",
    "api_shape": {
      "top_level": [
        "crawled_at",
        "took_ms",
        "total_candidates",
        "up",
        "with_feed",
        "with_handles",
        "total_handles",
        "products",
        "sites",
        "merged",
        "vendor_pairs"
      ],
      "gracie_site_required": [
        "slug",
        "host",
        "url",
        "type",
        "vendor",
        "up",
        "status",
        "title",
        "productCount",
        "feed",
        "products",
        "handles",
        "handleCount",
        "created_at"
      ]
    },
    "client_filters": {
      "initial": "sites.filter(s => s.up)",
      "default": "localStorage.adwm_filter or feeds; feeds requires s.feed",
      "all_sites_button": "#fAll (All Live Sites), persists adwm_filter=all",
      "catalogs_button": "#fFeeds (With Catalogs)",
      "search": "#q input, client state only; matches slug/title/vendor. No query-string initialization.",
      "card_selector": "a.card[href=\"https://gracie-internal.designerwallcoverings.com/\"]",
      "click": "target=_blank to s.url",
      "gate_display": "status===401 renders Trade Access badge and Trade-Gated field"
    }
  },
  "existing_seeds": {
    "brand": [
      {
        "slug": "gracie",
        "vendor": "Gracie",
        "knownProject": "~/Projects/dw-vendor-microsites/vendors/gracie",
        "note": "ONBOARDING/STAGING 2026-07-09 \u2014 ultra-luxury hand-painted scenic & chinoiserie wallpaper panels (Gracie Studio, est. 1898). 150 patterns in gracie_catalog (feed-first Next.js/Sanity page-data, $0). QUOTE-ONLY bespoke. Shopify DRAFT import gated (DWGA-, MANDATORY settlement-gate \u2014 chinoiserie is bird/butterfly/botanical heavy). Microsite deploy + DNS gated.",
        "hasMicrosite": true,
        "internalViewer": "http://127.0.0.1:10104 (~/Projects/gracie-internal, pm2 gracie-internal)"
      }
    ],
    "internal": [
      {
        "slug": "gracie-internal",
        "label": "Gracie \u2014 internal curation viewer",
        "note": "dw-vendor-microsites gracie internal viewer; Kamatera pm2 gracie-internal on :10105"
      }
    ],
    "already_seeded": true,
    "internal_issue": "Internal seed lacks internalViewer; note mentions obsolete10105. Brand seed already has10104. seedFromRegistry forwards internalViewer but ignores internal note (uses label)."
  },
  "local_snapshot": {
    "crawled_at": "2026-09-11T20:42:57.360Z",
    "sites": [
      {
        "slug": "gracie",
        "host": "gracie.designerwallcoverings.com",
        "url": "https://gracie.designerwallcoverings.com/",
        "type": "brand",
        "vendor": "Gracie",
        "note": "ONBOARDING/STAGING 2026-07-09 \u2014 ultra-luxury hand-painted scenic & chinoiserie wallpaper panels (Gracie Studio, est. 1898). 150 patterns in gracie_catalog (feed-first Next.js/Sanity page-data, $0). QUOTE-ONLY bespoke. Shopify DRAFT import gated (DWGA-, MANDATORY settlement-gate \u2014 chinoiserie is bird/butterfly/botanical heavy). Microsite deploy + DNS gated.",
        "pairSlug": null,
        "variant": null,
        "source": null,
        "created_at": null,
        "activeProductsDB": null,
        "up": true,
        "status": 401,
        "finalUrl": "https://gracie.designerwallcoverings.com/",
        "title": "Gracie",
        "hero": null,
        "productCount": 0,
        "feed": false,
        "handleCount": 0
      },
      {
        "slug": "gracie-internal",
        "host": "gracie-internal.designerwallcoverings.com",
        "url": "https://gracie-internal.designerwallcoverings.com/",
        "type": "internal",
        "vendor": null,
        "note": "Gracie \u2014 internal curation viewer",
        "pairSlug": null,
        "variant": null,
        "source": null,
        "created_at": null,
        "activeProductsDB": null,
        "up": true,
        "status": 401,
        "finalUrl": "https://gracie-internal.designerwallcoverings.com/",
        "title": "gracie-internal",
        "hero": null,
        "productCount": 0,
        "feed": false,
        "handleCount": 0
      }
    ],
    "scope_limit": "Local generated snapshot is not proof of current production state."
  },
  "crawl_behavior": {
    "401": "Healthy up=true, but no product feed is fetched for public401 unless explicit localhost internalViewer exists or unified vendor-pair logic applies.",
    "localhost_feed": "internalViewer regex extracts http://127.0.0.1:PORT or localhost; probes /api/products?limit=100000 then /api/skus?limit=100000&all=1.",
    "feed_shapes": "products endpoint: rows[] or products[], count from total/count; skus endpoint: rows[] or skus[], count from total/all/count. Nonempty array required.",
    "refresh": "Server starts crawl after initial snapshot and repeats every10minutes (30sec offset). API serves generated file with mtime cache.",
    "pair_caveat": "If production vendors snapshot includes Gracie, paired internal variant can merge with registry; when variant and up, crawler uses activeProductsDB and skips actual feed. Verify production rec.variant and activeProductsDB before assuming internalViewer alone resolves empty feeds.",
    "pm2_caveat": "seedFromPm2 strips -internal, so gracie-internal process fills gracie seed, not gracie-internal. Local source uses hard-coded Mac serialized PM2 helper; do not rely on it on Kamatera."
  },
  "reviewable_fix_if_production_matches": {
    "file": "config/known-subdomains.json",
    "entry": "internal[slug=gracie-internal]",
    "add_field": {
      "internalViewer": "http://127.0.0.1:10104 (~/Projects/gracie-internal, pm2 gracie-internal)"
    },
    "correct_note": "Replace obsolete10105 reference with verified10104; informational only.",
    "avoid_duplicate": "Do not add another gracie-internal entry; existing entry already seeds hostname.",
    "identity_limitation": "seedFromRegistry currently sets vendor=null for every internal entry; simply adding vendor to JSON will not create vendor drill-through. Not needed for hostname card."
  },
  "parent_e2e_assertions": [
    "Read production registry and /api/microsites before changing anything.",
    "Verify unique gracie-internal record URL matches authenticated hostname and up is true.",
    "If goal includes default directory visibility, verify feed true and productCount positive.",
    "Open /microsites.html, select All Live Sites, type gracie, assert intended card and link.",
    "Verify With Catalogs shows card after feed integration.",
    "Click card; assert Gracie authenticated page and unauthenticated401/noindex independently.",
    "Check positive handleCount and actual feed schema only if product membership needed; do not infer from health200."
  ],
  "deployment_rule": "CLAUDE.md: targeted changed files only; never sync data/ or full tree, never --delete. Parent owns any authorized rollout.",
  "separate_grid_note": "server.js defaults microsite product-grid Gracie feed to10073, independently overrideable with MICROSITE_FEED_PORTS; this is distinct from directory registry10104. Check existing production override only if grid ingestion is in scope.",
  "evidence_lines": {
    "registry": [
      68,
      73,
      125,
      127
    ],
    "scripts/crawl-microsites.js": [
      49,
      53,
      60,
      76,
      213,
      235,
      341,
      386,
      408,
      423,
      455,
      469
    ],
    "public/microsites.html": [
      187,
      264,
      321,
      350,
      360,
      473,
      477,
      478
    ],
    "server.js": [
      546,
      559,
      1033,
      1718,
      1745,
      1747
    ]
  },
  "source_sha256": {
    "server.js": "8d7265e888960fb0e8a298bb0f97e4d5c154baa57352f62524b4b607ebe74e0d",
    "scripts/crawl-microsites.js": "a5f4f54eee686e64f72d9460573c2dd2f309eb5bd0dcf7a9efeaf99a1fef941f",
    "public/microsites.html": "73113595c8061f11a067b88bfe1b85c210cc3ab2850f2c65cf060b68fa33db1b",
    "config/known-subdomains.json": "9abea7bb19e0c2f29e45c286a35ec599a78ef3b05f5917b55767a5e7f6822f0f",
    "lib/vendor-pairs.js": "b2c4c9fc9f00cb194a17f9f1b5583ada7823439c1c6e714c185b6e79c22ffc4f"
  }
}