Repository navigation
fix(public): enforce trust/support JSON-LD on the live site and deploy bundle #83
Changes from all commits
786e965
1fa65cb
4a0592f
aaaa24c
fa7e3c4
bb6ff20
7a52aba
78b5d78
9782547
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,12 +5,15 @@ | |
| // Used by the release lane after a Pages deployment. Runs against the live | ||
| // site only; set SKIP_LIVE_CHECKS=1 to skip (exit 0) on offline machines. | ||
| // | ||
| // The four live proofs (all neutral, all merged on main before this lane): | ||
| // The live proofs (all neutral, all merged on main before this lane): | ||
| // 1. /promptly/support/ renders H2 after H1 (PRs #18/#20) | ||
| // 2. /contact/ carries application/ld+json (PR #19) | ||
| // 3. unknown URLs get a real 404, not the homepage (PR #34) | ||
| // 4. homepage stays portfolio-only: brand-disambiguation copy (#29) live, | ||
| // and no managed-service buyer-path content (#10/#11, snoozed). | ||
| // 5. every public page carries exactly one application/ld+json block | ||
| // (trust/support structured data, PR #26 - the 07acd07 bundle shipped | ||
| // JSON-LD on only 4 of 12 pages). | ||
| import { join } from "node:path" | ||
| import { fileURLToPath } from "node:url" | ||
| import { dirname } from "node:path" | ||
|
|
@@ -24,6 +27,22 @@ const BUYER_PATH_MARKERS = [ | |
| "data-measure-source", | ||
| ] | ||
|
|
||
| // Every public page on the live site must carry structured data (PR #26). | ||
| const PUBLIC_PATHS = [ | ||
| "/", | ||
| "/contact/", | ||
| "/support/", | ||
| "/privacy/", | ||
| "/privacy-choices/", | ||
| "/terms/", | ||
| "/promptly/", | ||
| "/promptly/support/", | ||
| "/promptly/privacy/", | ||
| "/drishti/", | ||
| "/drishti/support/", | ||
| "/drishti/privacy/", | ||
| ] | ||
|
|
||
| let failures = 0 | ||
| let checks = 0 | ||
| const ok = (cond, msg) => { | ||
|
|
@@ -90,6 +109,13 @@ try { | |
| ok(!body.includes(marker), `homepage has no ${marker}`) | ||
| } | ||
| } | ||
| console.log("E. every public page carries structured data (PR #26)") | ||
| for (const path of PUBLIC_PATHS) { | ||
| const { status, body } = await get(path) | ||
| ok(status === 200, `${path} returns 200 (got ${status})`) | ||
| const blocks = (body.match(/<script\s+type="application\/ld\+json"[^>]*>/gi) || []).length | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a live response contains this opening-tag text inside an HTML comment, or contains one unterminated or syntactically invalid JSON-LD script, Useful? React with 👍 / 👎. |
||
| ok(blocks === 1, `${path} carries exactly one application/ld+json block (got ${blocks})`) | ||
|
Comment on lines
+116
to
+117
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a listed route is misconfigured to return another page with status 200—for example, Useful? React with 👍 / 👎. |
||
| } | ||
| } catch (error) { | ||
| failures++ | ||
| console.error(` FAIL live request error: ${error.message}`) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,8 @@ | |
| // - post-filter: the bundle must contain none of the forbidden markers and | ||
| // must still carry the neutral merged fixes used as deploy proof | ||
| // (H2-after-H1 on /promptly/support/ from #18/#20, JSON-LD on /contact/ | ||
| // from #19, homepage brand disambiguation from #29). | ||
| // from #19, homepage brand disambiguation from #29, and the PR #26 | ||
| // site-wide invariant that every public page keeps its JSON-LD block). | ||
| // | ||
| // CLI: node scripts/prepare-public-deploy-bundle.mjs --source public --output <dir> | ||
| // Defaults: --source ./public, --output to a fresh temp directory (printed). | ||
|
|
@@ -80,6 +81,59 @@ export const NEUTRAL_PROOFS = [ | |
| file: "index.html", | ||
| test: (html) => html.includes("not affiliated"), | ||
| }, | ||
| // Site-wide structured data invariant (PR #26): the 07acd07 bundle shipped | ||
| // JSON-LD on only 4 of 12 pages; the release lane must never do that again. | ||
| // Each remaining public page keeps exactly one application/ld+json block. | ||
| { | ||
| label: "support page JSON-LD (07acd07 baseline)", | ||
| file: "support/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a page loses its JSON-LD Useful? React with 👍 / 👎. |
||
| }, | ||
| { | ||
| label: "privacy hub JSON-LD (PR #26)", | ||
| file: "privacy/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| { | ||
| label: "terms page JSON-LD (PR #26)", | ||
| file: "terms/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| { | ||
| label: "privacy choices JSON-LD (PR #26)", | ||
| file: "privacy-choices/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| { | ||
| label: "Promptly home JSON-LD (07acd07 baseline)", | ||
| file: "promptly/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| { | ||
| label: "Promptly support JSON-LD (PR #26)", | ||
| file: "promptly/support/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| { | ||
| label: "Promptly privacy JSON-LD (PRs #19/#26)", | ||
| file: "promptly/privacy/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| { | ||
| label: "Drishti home JSON-LD (07acd07 baseline)", | ||
| file: "drishti/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| { | ||
| label: "Drishti support JSON-LD (PR #26)", | ||
| file: "drishti/support/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| { | ||
| label: "Drishti privacy JSON-LD (PR #26)", | ||
| file: "drishti/privacy/index.html", | ||
| test: (html) => html.includes("application/ld+json"), | ||
| }, | ||
| ] | ||
|
|
||
| // Files that must exist in every bundle. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a new
public/**/index.htmlpage is added, the bundle copies and publishes it but this manually maintained array does not automatically include it, so the claimed site-wide live invariant silently stops at the original 12 routes. This is especially problematic for detecting another stale deployment: the new route can be absent or lack JSON-LD while post-deploy verification succeeds. Derive this inventory from the deploy bundle or another canonical route manifest, or add a synchronization check against the public pages.Useful? React with 👍 / 👎.