Skip to content
Skip to main content
Novel Systems home
Decision log
D-007August 3, 2026Accepted

The link checker asks what it can answer without the network

Affects: scripts/check-links.mjs, lib/contact-configuration.ts, components/CPQSandbox.tsx

The link audit checked three things: internal routes resolve, anchors exist, and the sitemap is backed by pages. It now checks six. The three additions were each chosen because a real defect in this repository passed all three original checks while being broken.

Call-to-action intent. app/integrations/page.tsx linked to /contact?source=integrations and components/auth/trial-signup.tsx linked to /contact?source=signup. Both routes resolved. Both anchors were absent. Both were in the sitemap. And /contact read neither value — ReferralSourceId was the single string "security" — so the query was stripped on arrival and the visitor landed on the generic form. This is the worst shape of defect the site has: it is invisible in every automated check, invisible in manual clicking because the page does load, and the only person who notices is a salesperson wondering why a lead has no context. Both sources now exist with real copy, and the checker fails on a ?source= value /contact does not read.

The checker cannot import the TypeScript module that owns those values — it runs under bare node before any build step — so it parses RECOGNISED_CONTACT_SOURCES textually, the way check-margin-policy.mjs parses the margin floor. Textual parsing invites drift, so the array is pinned to the two parsers by a bidirectional compile-time assertion in lib/contact-configuration.ts: listing a source nothing reads is a type error, and so is adding a source without listing it. The assertion is assigned to an exported const rather than left as a type alias, because an unreferenced alias is erased and never evaluated — it would have compiled no matter what it said. Both directions were verified by deleting entries and confirming tsc fails.

Placeholder hrefs. #, "", and javascript: are not dead routes, so nothing above sees them, and a bare # is specifically hard to catch by hand because on a short page it looks exactly like a link that worked. #section is deliberately left alone; that is a real anchor and check 2 already has an opinion about it.

External destinations. External links are still not fetched. A build step that makes network calls to third-party sites fails when somebody else has an outage, and that failure says nothing about this repository. But that argument only covers liveness. Whether a URL parses, has a real host, is https rather than a downgrade, and severs window.opener when it opens a new tab are all answerable statically, and all belong to this repository rather than to the destination. components/CPQSandbox.tsx had target="_blank" with rel="noreferrer" and no noopener — every current browser implies noopener there, which is exactly why it is worth a build check: the protection is invisible, so its absence is invisible too, and it is absent in any embedded webview an enterprise customer happens to be running. The footer already stated the both-tokens rule in a comment; a rule stated in a comment and enforced nowhere holds until the next component.

URLs are collected by shape, not by property name. A checker keyed on href and docsUrl stops covering the codebase the day somebody adds vendorUrl, and stops silently.

What was deliberately not added. A placeholder-domain check — example.com, your-project-ref — was written and then removed. lib/supabase.ts maintains PLACEHOLDER_VALUES as a deliberate reject-list, and https://your-project-ref.supabase.co appears there as a value to refuse, not a destination to visit. It parses, it is https, and its host is a real domain, so it passes every remaining check honestly. Building an exclusion mechanism so one check could ignore a file it should never have flagged is more machinery than the check is worth, and the script's own governing principle applies: a check that cries wolf on correct code is a check that gets deleted within a week.

How this was verified. Not by observing a green run. Each of the four new failure modes was introduced deliberately — an unrecognised ?source=, a bare # href, an http:// URL, a hostless one, and a stripped noopener — and the script was confirmed to name each one and exit 1 before the code was restored. A guard nobody has watched fail is a guard nobody knows works.

This would be wrong if external URLs started being assembled from parts often enough that literal-scanning missed most of them, at which point the check would be reporting on a shrinking minority while reading as coverage.