[object Object]

← back to Tk11438 Postgres Migration

Verify existing Gracie domain and All-DW catalog link

469a2b2e3a1e462d2400236b3b44025d4f9667c1 · 2026-09-11 14:42:55 -0700 · Steve Abrams

Files touched

Diff

commit 469a2b2e3a1e462d2400236b3b44025d4f9667c1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Sep 11 14:42:55 2026 -0700

    Verify existing Gracie domain and All-DW catalog link
---
 verification/tk11517-domain/all-gracie.png         | Bin 0 -> 85555 bytes
 verification/tk11517-domain/browser-check.cjs      |  28 +++
 verification/tk11517-domain/browser-proof.json     |  33 ++++
 verification/tk11517-domain/directory-review.json  | 200 +++++++++++++++++++
 verification/tk11517-domain/e2e-proof.json         |  62 ++++++
 verification/tk11517-domain/gracie-live.png        | Bin 0 -> 71139 bytes
 verification/tk11517-domain/live-verification.json | 212 +++++++++++++++++++++
 .../tk11517-domain/urllib-verification.json        | 168 ++++++++++++++++
 verification/tk11517-domain/verify-existing.py     |  46 +++++
 9 files changed, 749 insertions(+)

diff --git a/verification/tk11517-domain/all-gracie.png b/verification/tk11517-domain/all-gracie.png
new file mode 100644
index 0000000..0ac12bf
Binary files /dev/null and b/verification/tk11517-domain/all-gracie.png differ
diff --git a/verification/tk11517-domain/browser-check.cjs b/verification/tk11517-domain/browser-check.cjs
new file mode 100644
index 0000000..029f7e5
--- /dev/null
+++ b/verification/tk11517-domain/browser-check.cjs
@@ -0,0 +1,28 @@
+const fs=require('fs'),assert=require('assert/strict');
+const {chromium}=require('/Users/macstudio3/.agents/skills/hero-readability-auditor/node_modules/playwright');
+const src=fs.readFileSync('/Users/macstudio3/Projects/all-designerwallcoverings/server.js','utf8');
+const auth=src.match(/['"](admin:[^'"]+)['"]/)[1];
+const hosts=new Set(['all.designerwallcoverings.com','gracie-internal.designerwallcoverings.com']);
+const profile='/tmp/tk11517-browser-profile',out='/tmp/tk11517-browser-proof.json';
+fs.mkdirSync(profile,{recursive:true,mode:0o700});fs.chmodSync(profile,0o700);
+(async()=>{
+ const browser=await chromium.launchPersistentContext(profile,{channel:'chrome',headless:false,viewport:{width:1440,height:1000}});
+ const proof={ticket:'TK-11517',at:new Date().toISOString(),checks:[],application_mutations:0,email_sends:0},errors=[];
+ try{
+  await browser.route('**/*',async route=>{const request=route.request(),headers={...request.headers()};if(hosts.has(new URL(request.url()).hostname))headers.authorization='Basic '+Buffer.from(auth).toString('base64');else delete headers.authorization;await route.continue({headers});});
+  const page=await browser.newPage();page.on('pageerror',e=>errors.push(e.message));
+  const response=await page.goto('https://all.designerwallcoverings.com/microsites.html',{waitUntil:'domcontentloaded',timeout:30000});assert.equal(response.status(),200);
+  // The grid renders batches. Search before waiting for a card beyond the first batch.
+  await page.locator('#q').waitFor({state:'visible'});await page.locator('#fFeeds').click();
+  await page.locator('#q').fill('gracie');
+  const card=page.locator('a.card[href="https://gracie-internal.designerwallcoverings.com/"]');await card.waitFor({state:'visible',timeout:30000});assert.equal(await card.count(),1);
+  proof.checks.push({name:'Gracie visible under With Catalogs after search',pass:true});
+  const text=await card.innerText();assert(text.includes('150'));proof.checks.push({name:'Search Gracie yields unique internal card with150products',pass:true,text});
+  await page.screenshot({path:'/tmp/tk11517-all-gracie.png',fullPage:false});
+  const [popup]=await Promise.all([page.waitForEvent('popup'),card.click()]);await popup.waitForURL('https://gracie-internal.designerwallcoverings.com/**',{waitUntil:'domcontentloaded',timeout:30000});assert.equal(new URL(popup.url()).hostname,'gracie-internal.designerwallcoverings.com');await popup.waitForFunction(()=>document.body.innerText.includes('Gracie'),null,{timeout:15000});
+  const api=await popup.evaluate(async()=>{const r=await fetch('/api/products');const d=await r.json();return{status:r.status,count:d.count};});assert.equal(api.status,200);assert.equal(api.count,150);
+  proof.checks.push({name:'Actual directory click opens authenticated Gracie with150products',pass:true,url:popup.url(),title:await popup.title(),api});
+  await popup.screenshot({path:'/tmp/tk11517-gracie-live.png',fullPage:false});proof.page_errors=errors;assert.equal(errors.length,0);
+  proof.verdict='PASS';proof.screenshots=['/tmp/tk11517-all-gracie.png','/tmp/tk11517-gracie-live.png'];
+ }catch(e){proof.verdict='FAIL';proof.error=e.message;const p=browser.pages().at(-1);if(p){proof.page={url:p.url(),text:(await p.locator('body').innerText()).slice(0,1800)};await p.screenshot({path:'/tmp/tk11517-browser-failure.png'}).catch(()=>{});}process.exitCode=1;}finally{fs.writeFileSync(out,JSON.stringify(proof,null,2)+'\n');await browser.close();console.log(JSON.stringify(proof,null,2));}
+})().catch(e=>{console.error(e.message);process.exitCode=1;});
diff --git a/verification/tk11517-domain/browser-proof.json b/verification/tk11517-domain/browser-proof.json
new file mode 100644
index 0000000..f3b872c
--- /dev/null
+++ b/verification/tk11517-domain/browser-proof.json
@@ -0,0 +1,33 @@
+{
+  "ticket": "TK-11517",
+  "at": "2026-09-11T21:40:04.019Z",
+  "checks": [
+    {
+      "name": "Gracie visible under With Catalogs after search",
+      "pass": true
+    },
+    {
+      "name": "Search Gracie yields unique internal card with150products",
+      "pass": true,
+      "text": "150 DESIGNS\nG\nGracie — Internal Line Viewer\n150 DESIGNS\nCREATED 🕓 —\nVISIT MICROSITE →\n✉ STOCK & PRICE"
+    },
+    {
+      "name": "Actual directory click opens authenticated Gracie with150products",
+      "pass": true,
+      "url": "https://gracie-internal.designerwallcoverings.com/",
+      "title": "Gracie — Internal Line Viewer",
+      "api": {
+        "status": 200,
+        "count": 150
+      }
+    }
+  ],
+  "application_mutations": 0,
+  "email_sends": 0,
+  "page_errors": [],
+  "verdict": "PASS",
+  "screenshots": [
+    "/tmp/tk11517-all-gracie.png",
+    "/tmp/tk11517-gracie-live.png"
+  ]
+}
diff --git a/verification/tk11517-domain/directory-review.json b/verification/tk11517-domain/directory-review.json
new file mode 100644
index 0000000..4a7a64f
--- /dev/null
+++ b/verification/tk11517-domain/directory-review.json
@@ -0,0 +1,200 @@
+{
+  "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"
+  }
+}
diff --git a/verification/tk11517-domain/e2e-proof.json b/verification/tk11517-domain/e2e-proof.json
new file mode 100644
index 0000000..e6bfc2f
--- /dev/null
+++ b/verification/tk11517-domain/e2e-proof.json
@@ -0,0 +1,62 @@
+{
+  "ticket": "TK-11517-serve-authenticated-gracie-internal-doma",
+  "at": "2026-09-11T21:42:55.065339+00:00",
+  "verdict": "PASS",
+  "risk_tier": "R3 authenticated read-only verification",
+  "intent": "Serve Gracie authenticated hostname and include its working link in All-DW",
+  "outcome": "Existing production deployment and directory already fulfill request; no duplicate/redeploy needed",
+  "gracie_url": "https://gracie-internal.designerwallcoverings.com/",
+  "directory_url": "https://all.designerwallcoverings.com/microsites.html",
+  "entry": {
+    "slug": "gracie-internal",
+    "url": "https://gracie-internal.designerwallcoverings.com/",
+    "type": "internal",
+    "vendor": null,
+    "variant": null,
+    "up": true,
+    "status": 200,
+    "title": "Gracie \u2014 Internal Line Viewer",
+    "productCount": 150,
+    "feed": true,
+    "handleCount": 150
+  },
+  "http_checks": 15,
+  "browser_checks": [
+    {
+      "name": "Gracie visible under With Catalogs after search",
+      "pass": true
+    },
+    {
+      "name": "Search Gracie yields unique internal card with150products",
+      "pass": true,
+      "text": "150 DESIGNS\nG\nGracie \u2014 Internal Line Viewer\n150 DESIGNS\nCREATED \ud83d\udd53 \u2014\nVISIT MICROSITE \u2192\n\u2709 STOCK & PRICE"
+    },
+    {
+      "name": "Actual directory click opens authenticated Gracie with150products",
+      "pass": true,
+      "url": "https://gracie-internal.designerwallcoverings.com/",
+      "title": "Gracie \u2014 Internal Line Viewer",
+      "api": {
+        "status": 200,
+        "count": 150
+      }
+    }
+  ],
+  "commands": [
+    "DNS resolution",
+    "SSH read nginx/current registry/snapshot",
+    "curl authenticated and negative HTTPS checks using stdin config",
+    "Isolated browser search,cardclick and GracieAPI proof"
+  ],
+  "application_mutations": 0,
+  "dns_mutations": 0,
+  "restarts": 0,
+  "email_sends": 0,
+  "private_access": "Both sites reject absent/invalid credentials401; validcredentials200; Gracie noindex/nofollow",
+  "notes": [
+    "Initial urllib client403 retained; standardcurl/browser pass without edge changes",
+    "Directory uses batched rendering; search used before locating card",
+    "Mac Gracie socket migration retained; Kamatera existing service remains on10104",
+    "TK11438 parent fleet migration remains incomplete and is not closed"
+  ]
+}
diff --git a/verification/tk11517-domain/gracie-live.png b/verification/tk11517-domain/gracie-live.png
new file mode 100644
index 0000000..4044792
Binary files /dev/null and b/verification/tk11517-domain/gracie-live.png differ
diff --git a/verification/tk11517-domain/live-verification.json b/verification/tk11517-domain/live-verification.json
new file mode 100644
index 0000000..c643a87
--- /dev/null
+++ b/verification/tk11517-domain/live-verification.json
@@ -0,0 +1,212 @@
+{
+  "task": "TK-11517",
+  "checks": [
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/",
+      "auth": "missing",
+      "status": 401,
+      "bytes": 1434,
+      "body_sha256": "521ada55b4a198d82072e94b63e7f4a1d38aae6a2e578159c0c9f37de853d9c0",
+      "robots": "noindex, nofollow"
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/",
+      "auth": "invalid",
+      "status": 401,
+      "bytes": 1436,
+      "body_sha256": "c55cdcbc1b0c66319c6955776946478e9facad613e0189eb2c8be57a786a4c90",
+      "robots": "noindex, nofollow"
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/",
+      "auth": "valid",
+      "status": 200,
+      "bytes": 23971,
+      "body_sha256": "c8c84f1799108c59b64994427690aec1f440b0ede9b0cac15bbc2776a46b7088",
+      "robots": "noindex, nofollow"
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/api/products",
+      "auth": "missing",
+      "status": 401,
+      "bytes": 1436,
+      "body_sha256": "0d593aedf0eaefe991533492b3547c85f8fe466e0c9a6b811a42980cec0538bc",
+      "robots": "noindex, nofollow"
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/api/products",
+      "auth": "invalid",
+      "status": 401,
+      "bytes": 1436,
+      "body_sha256": "27ce6a905e6dc33a2ea4f83e560f7990569bb1eec8e70fc2289c5294d5c932d0",
+      "robots": "noindex, nofollow"
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/api/products",
+      "auth": "valid",
+      "status": 200,
+      "bytes": 188603,
+      "body_sha256": "b01acb69f4bd1d7d3c64d4dead18b84cf7f7026e9a702a2e9a77b08f66940264",
+      "robots": "noindex, nofollow",
+      "count": 150
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/",
+      "auth": "missing",
+      "status": 401,
+      "bytes": 23,
+      "body_sha256": "0fcfb12dfad07ba0b1ab80f7cd6c6c3c5aaea0804be09faee6ca0819e3769659",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/",
+      "auth": "invalid",
+      "status": 401,
+      "bytes": 23,
+      "body_sha256": "0fcfb12dfad07ba0b1ab80f7cd6c6c3c5aaea0804be09faee6ca0819e3769659",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/",
+      "auth": "valid",
+      "status": 200,
+      "bytes": 91422,
+      "body_sha256": "3644f6a9339f86828b9da9073a950ffecefb03b64d3ff7339fbea161ee79fdbc",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/api/microsites",
+      "auth": "missing",
+      "status": 401,
+      "bytes": 23,
+      "body_sha256": "0fcfb12dfad07ba0b1ab80f7cd6c6c3c5aaea0804be09faee6ca0819e3769659",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/api/microsites",
+      "auth": "invalid",
+      "status": 401,
+      "bytes": 23,
+      "body_sha256": "0fcfb12dfad07ba0b1ab80f7cd6c6c3c5aaea0804be09faee6ca0819e3769659",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/api/microsites",
+      "auth": "valid",
+      "status": 200,
+      "bytes": 2803018,
+      "body_sha256": "55e324df62785b363fb1c3e6313d480e49d1a32cfe77a9bd0a399e2dc68c378f",
+      "robots": null,
+      "response_keys": [
+        "crawled_at",
+        "took_ms",
+        "total_candidates",
+        "up",
+        "with_feed",
+        "with_handles",
+        "total_handles",
+        "products",
+        "sites",
+        "merged",
+        "vendor_pairs"
+      ],
+      "sites_total": 1097,
+      "gracie": [
+        {
+          "slug": "gracie",
+          "url": "https://gracie.designerwallcoverings.com/",
+          "type": "brand",
+          "vendor": "Gracie",
+          "variant": null,
+          "up": true,
+          "status": 200,
+          "title": "Trade Lines",
+          "productCount": 150,
+          "feed": true,
+          "handleCount": 150
+        },
+        {
+          "slug": "gracie-internal",
+          "url": "https://gracie-internal.designerwallcoverings.com/",
+          "type": "internal",
+          "vendor": null,
+          "variant": null,
+          "up": true,
+          "status": 200,
+          "title": "Gracie \u2014 Internal Line Viewer",
+          "productCount": 150,
+          "feed": true,
+          "handleCount": 150
+        }
+      ],
+      "snapshot_timestamp": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/microsites.html",
+      "auth": "missing",
+      "status": 401,
+      "bytes": 23,
+      "body_sha256": "0fcfb12dfad07ba0b1ab80f7cd6c6c3c5aaea0804be09faee6ca0819e3769659",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/microsites.html",
+      "auth": "invalid",
+      "status": 401,
+      "bytes": 23,
+      "body_sha256": "0fcfb12dfad07ba0b1ab80f7cd6c6c3c5aaea0804be09faee6ca0819e3769659",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/microsites.html",
+      "auth": "valid",
+      "status": 200,
+      "bytes": 30280,
+      "body_sha256": "ad23b9f51ad7285778d4ca37eb0e17b99364d9e197ff21b2a41b3c54d8863865",
+      "robots": null
+    }
+  ],
+  "application_mutations": 0,
+  "email_sends": 0,
+  "registry_gracie": {
+    "brands": [
+      {
+        "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"
+      }
+    ]
+  },
+  "gracie_saved_metadata": {
+    "name": "gracie-internal",
+    "pm_exec_path": "/root/Projects/gracie-internal/server.js",
+    "pm_cwd": "/root/Projects/gracie-internal",
+    "PORT": "10104",
+    "DATA_SOURCE": "jsonl"
+  }
+}
diff --git a/verification/tk11517-domain/urllib-verification.json b/verification/tk11517-domain/urllib-verification.json
new file mode 100644
index 0000000..a32b671
--- /dev/null
+++ b/verification/tk11517-domain/urllib-verification.json
@@ -0,0 +1,168 @@
+{
+  "task": "TK-11517",
+  "checks": [
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/",
+      "auth": "missing",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/",
+      "auth": "invalid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/",
+      "auth": "valid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/api/products",
+      "auth": "missing",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/api/products",
+      "auth": "invalid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "gracie-internal.designerwallcoverings.com",
+      "route": "/api/products",
+      "auth": "valid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/",
+      "auth": "missing",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/",
+      "auth": "invalid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/",
+      "auth": "valid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/api/microsites",
+      "auth": "missing",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/api/microsites",
+      "auth": "invalid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/api/microsites",
+      "auth": "valid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/microsites.html",
+      "auth": "missing",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/microsites.html",
+      "auth": "invalid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    },
+    {
+      "host": "all.designerwallcoverings.com",
+      "route": "/microsites.html",
+      "auth": "valid",
+      "status": 403,
+      "bytes": 17,
+      "body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
+      "robots": null
+    }
+  ],
+  "application_mutations": 0,
+  "email_sends": 0,
+  "registry_gracie": {
+    "brands": [
+      {
+        "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"
+      }
+    ]
+  },
+  "gracie_saved_metadata": {
+    "name": "gracie-internal",
+    "pm_exec_path": "/root/Projects/gracie-internal/server.js",
+    "pm_cwd": "/root/Projects/gracie-internal",
+    "PORT": "10104",
+    "DATA_SOURCE": "jsonl"
+  }
+}
diff --git a/verification/tk11517-domain/verify-existing.py b/verification/tk11517-domain/verify-existing.py
new file mode 100644
index 0000000..fdbb4b3
--- /dev/null
+++ b/verification/tk11517-domain/verify-existing.py
@@ -0,0 +1,46 @@
+import base64,hashlib,json,pathlib,re,urllib.request,urllib.error,subprocess
+root=pathlib.Path('/root/Projects')
+dump=json.loads(pathlib.Path('/root/.pm2/dump.pm2').read_text())
+def effective(name):
+ rows=[x for x in dump if x.get('name')==name]
+ return rows[0] if len(rows)==1 else {}
+def fileenv(p):
+ if not p.exists():return {}
+ return {m[1]:m[2].strip().strip('"\'') for m in re.finditer(r'^([A-Z_][A-Z0-9_]*)=(.*)$',p.read_text(),re.M)}
+allroot=root/'all-designerwallcoverings';source=(allroot/'server.js').read_text()
+env={**fileenv(allroot/'.env'),**effective('all-designerwallcoverings')}
+auth=env.get('BASIC_AUTH') or (env.get('BASIC_AUTH_USER','')+':'+env.get('BASIC_AUTH_PASS','') if env.get('BASIC_AUTH_PASS') else None)
+auth=auth or re.search(r"['\"](admin:[^'\"]+)['\"]",source)[1]
+class NoRedirect(urllib.request.HTTPRedirectHandler):
+ def redirect_request(self,*args,**kwargs):return None
+class CurlResponse:
+ def __init__(self,request):
+  config='url = '+json.dumps(request.full_url)+'\n'
+  for key,val in request.header_items():config+='header = '+json.dumps(key+': '+val)+'\n'
+  r=subprocess.run(['curl','--silent','--show-error','--include','--max-time','15','--config','-'],input=config.encode(),capture_output=True,timeout=20)
+  if r.returncode:raise RuntimeError('curl failed '+str(r.returncode))
+  head,body=r.stdout.split(b'\r\n\r\n',1)
+  while body.startswith(b'HTTP/'):
+   head,body=body.split(b'\r\n\r\n',1)
+  self.code=int(head.splitlines()[0].split()[1]);self.body=body
+  self.headers={k.decode().lower():v.decode().strip() for l in head.splitlines()[1:] if b':' in l for k,v in [l.split(b':',1)]}
+ def read(self):return self.body
+proof={'task':'TK-11517','checks':[],'application_mutations':0,'email_sends':0}
+for host,route in [('gracie-internal.designerwallcoverings.com','/'),('gracie-internal.designerwallcoverings.com','/api/products'),('all.designerwallcoverings.com','/'),('all.designerwallcoverings.com','/api/microsites'),('all.designerwallcoverings.com','/microsites.html')]:
+ for label,credential in [('missing',None),('invalid','TK11517:invalid'),('valid',auth)]:
+  request=urllib.request.Request('https://'+host+route,headers={'Authorization':'Basic '+base64.b64encode(credential.encode()).decode()} if credential else {})
+  response=CurlResponse(request)
+  body=response.read();item={'host':host,'route':route,'auth':label,'status':response.code,'bytes':len(body),'body_sha256':hashlib.sha256(body).hexdigest(),'robots':response.headers.get('x-robots-tag')}
+  if label=='valid' and response.code==200:
+   if route=='/api/products':
+    d=json.loads(body);item['count']=d.get('count',len(d.get('products',[])))
+   if route=='/api/microsites':
+    d=json.loads(body);item['response_keys']=list(d);sites=d.get('sites',d.get('microsites',[]));item['sites_total']=len(sites)
+    item['gracie']=[{k:v for k,v in s.items() if k in ['slug','url','domain','vendor','title','type','status','ok','up','http_status','productCount','handleCount','count','feed','internalViewer','variant','name','feed_count','public_url','error','feed_url']} for s in sites if 'gracie' in s.get('slug','').lower()]
+    item['snapshot_timestamp']=d.get('at') or d.get('updated_at') or d.get('generated_at')
+  proof['checks'].append(item)
+reg=allroot/'config/known-subdomains.json'
+if reg.exists():
+ d=json.loads(reg.read_text());proof['registry_gracie']={k:[v for v in vals if 'gracie' in json.dumps(v).lower()] for k,vals in d.items() if isinstance(vals,list)}
+proof['gracie_saved_metadata']={k:v for k,v in effective('gracie-internal').items() if k in ['name','pm_cwd','pm_exec_path','PORT','DATA_SOURCE']}
+print(json.dumps(proof,indent=2))

← 676734b Record verified private Gracie socket migration  ·  back to Tk11438 Postgres Migration  ·  Save session closeout and remaining PostgreSQL migration han 7dd2703 →