Repository navigation
fix(public): enforce trust/support JSON-LD on the live site and deploy bundle #83
Changes from 7 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 👍 / 👎.