Skip to content
Skip to main content
Novel Systems home
Decision log
D-094August 6, 2026

Named customers came off the site, and a self-declared status was replaced by a committed artifact

Affects: lib/customer-proof.ts, components/marketing/scenario-card.tsx, components/marketing/case-study-card.tsx (deleted), components/marketing/social-proof.tsx, scripts/check-proof-copy.mjs, app/page.tsx, app/pricing/page.tsx, app/platform/cpq/page.tsx, app/platform/fms/page.tsx

Decision

Remove every named third-party company and every attributed testimonial from the marketing surfaces. Delete the TestimonialStatus = "placeholder" | "approved" enum and replace it with consentRecord: string, a repository-relative path to a committed permission artifact that the build resolves against the filesystem. Delete PLATFORM_MILESTONES in the same pass.

What happened

An outside reviewer compared two visits and reported that five customer names had been replaced by five different ones: "Apex Commercial Electrical", "Vanguard Mechanical", "Metro Trade", "Ontario Shading" and "Trillium Industrial" became "Lloyd's Electric", "Haller Mechanical", "Spark Power", "J & S Heating" and "Borealis Electric".

He filed it as a consistency problem. It is not. Real references do not get renamed. The wholesale swap is the evidence that the names were authored rather than recorded — and at least one of them, Spark Power, is a real and identifiable Ontario energy-services firm, quoted by name and title through an invented "Sarah Jenkins, Regional Operations Manager". That is a false-endorsement exposure, not a credibility wobble, and it is materially worse than anything in the review.

Why the previous guard did not catch it

scripts/check-proof-copy.mjs existed for exactly this. It warned — deliberately did not fail — while a quote was still placeholder, and failed hard if an approved quote still carried draft text. Its own header argued that failing on a placeholder would make writing the word "approved" the cheapest route to a green build, and that a control whose cheapest exit is the unsafe state is worse than no control.

The argument was correct and the script shipped anyway with that exit open, because nothing else stood in front of it. On 4 August 2026 five fabricated testimonials moved from placeholder to approved in a single edit and every check passed. They passed because the quotes contained no draft markers, which is what invented copy looks like. The guard was measuring polish.

So the enum is gone and the script no longer inspects wording at all. The invariant is now: a published quotation must cite a file path, and that file must exist. A path is not a word. It cannot be satisfied by typing something more confident.

Why the type lost its name field rather than having it blanked

TradeOperator became TradeSegment and the name and shortName fields were removed outright rather than emptied. A type with a name field on it invites the next person to fill it in, and the last two times this file changed hands that is precisely what happened. TRADE_SEGMENTS now carries segments — "Multi-trade general", "Mechanical contracting" — which are descriptions of an industry rather than claims about a customer.

CASE_STUDIES became DEPLOYMENT_SCENARIOS and case-study-card.tsx became scenario-card.tsx, because a case study is an account of what happened at a named customer and this component has never rendered one of those. The results rows were recast from customer outcomes to engine mechanisms: "Bid turnaround / Same day / as reported by the estimating team" is gone; "Margin check / At the line" remains, and is confirmable by operating the product at the linked scenario.

Why the milestone banner went too

PLATFORM_MILESTONES published "$697K+ ARR", "41 enterprise trade accounts", "95%+ forecast accuracy" and "3 mo sales velocity". Those were already flagged as D1/D2 in docs/legal/FLAGGED-CLAIMS.md. Once the named accounts were gone, a banner asserting forty-one enterprise customers on a site that can no longer name one is not merely unsupported, it is internally contradictory on the same page. Any substitute figure is a figure somebody has to keep true, and keeping numbers true between visits is the thing this review found the site failing at. The honest move is that the claim stops being made.

What would make this wrong

A real customer giving real, written, retrievable permission. That is the only route back, and docs/legal/CASE-STUDY-INTAKE.md describes it. The path they consent through is committed to this repository and cited from the data, so it can be produced later if anybody asks. An approval that cannot be produced later is not an approval.