Skip to content
This repository was archived by the owner on Oct 12, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion scripts/check-public-live-deploy.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 = [

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive live paths from the public-page inventory

When a new public/**/index.html page 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 👍 / 👎.

"/",
"/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) => {
Expand Down Expand Up @@ -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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require complete, parseable JSON-LD blocks

When a live response contains this opening-tag text inside an HTML comment, or contains one unterminated or syntactically invalid JSON-LD script, blocks is still 1, so section E reports success even though consumers have no usable structured data. This live acceptance check should extract complete opening/closing script blocks and parse their contents as JSON before counting them as valid.

Useful? React with 👍 / 👎.

ok(blocks === 1, `${path} carries exactly one application/ld+json block (got ${blocks})`)
Comment on lines +116 to +117

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify that each response matches its requested route

When a listed route is misconfigured to return another page with status 200—for example, /drishti/privacy/ serving the homepage—this check passes because the homepage also contains exactly one JSON-LD opening tag. The unknown-URL test does not detect a rewrite or duplicated artifact affecting only a known route, so the release lane can approve a deployment where the requested page and its route-specific structured data are absent; compare the response canonical or parsed JSON-LD URL with path before accepting it.

Useful? React with 👍 / 👎.

}
} catch (error) {
failures++
console.error(` FAIL live request error: ${error.message}`)
Expand Down
56 changes: 55 additions & 1 deletion scripts/prepare-public-deploy-bundle.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate an actual JSON-LD block in bundle proofs

When a page loses its JSON-LD <script> but retains the text application/ld+json elsewhere—for example, in an HTML comment—this proof still passes, so preparePublicDeployBundle() can produce a publishable bundle without structured data despite the stated fail-closed invariant. This affects every newly added proof because they all use the same substring check; count complete JSON-LD script blocks (and require exactly one) instead.

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.
Expand Down
Loading