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

Renaming the tenant did not cover the client field, and the client field named eighteen real organisations

Affects: lib/tenant-workspaces.ts, lib/trade-quoting.ts, lib/fms-data.ts, components/fsm/work-order-geography.ts, scripts/check-proof-copy.mjs

Decision

Every named third-party organisation was removed from the demo tenant fixtures and replaced with a facility type. The removed-names guard, which had been scoped to a single file, now walks the whole shipped source tree and carries both the fabricated names and the real ones.

What forced it

D-096, earlier the same day, renamed the three demo tenants to "Sample Workspace — …" so that the disclosure would travel with the value instead of sitting in a caption four lines below it. Extending the removed-names check past its original file, which was the follow-on task, is what surfaced the rest.

The tenants' work orders and quotes were filled with the names of eighteen real, identifiable Ontario organisations. A transit agency. Two hospital networks. Two universities and a college. A municipality and a regional government. A steel producer, a food processor, and several of the largest commercial landlords in the country. Each was given a named building, a scope, a crew, a dollar value, and on the quote side a gross margin. Two of the five case-study companies removed on 4 August were also still there, as clients rather than as studies.

Nobody was asked. Nobody consented. None of them are customers.

Why the D-096 rename was not enough

The disclosure that went into the tenant name qualifies the account holder. It does not reach the counterparty, and these fields are the counterparty. What the dispatch board rendered after D-096 and before this change was, in substance:

Sample Workspace — Multi-Trade Contractor · $412,000 quote out to Cadillac Fairview · 30% margin

That sentence discloses that the contractor is fictional and asserts, on the same line and with the same authority, that the landlord is not. It is a worse sentence than the one it replaced, because the visible honesty about one party lends credibility to the unconsented claim about the other. This is the D-069 / D-071 / D-095 placement failure arriving from the other direction: not a disclosure too far from the claim, but a disclosure that covers the wrong half of it.

It is also a more serious category of error than D-094. The aggravating fact recorded there was that one of five invented names, Spark Power Corp, turned out to belong to a real Ontario firm. Here all eighteen are real, and several are public bodies. Publishing a hospital network as a counterparty on a margin figure is not a copy problem.

Why facility types rather than obviously-fake names

A fixture reading "Acme Corp" would be safe and would also stop the surface demonstrating anything: the reader is being shown that a work order carries a client, a site, a scope and a value, and joke names make that read as a toy. A facility type — "Regional hospital network", "Enclosed shopping centre", "Primary steel producer" — carries the same information as a masthead does, because what makes the board legible is the *kind* of building, not whose name is on it. It is descriptive rather than referential, which is the property that was missing.

What was deliberately not changed

The coordinates. components/fsm/work-order-geography.ts still places each work order on a real commercial address in the stated municipality, and its header explains why: a demo that quotes a drive time and measures it to a hashed point produces a plausible number nobody can defend. A latitude identifies a place. A client field identifies a party. Only the second was ever a claim about someone.

The street addresses in `lib/fms-data.ts`. Those fixtures pair invented firm names with real addresses. An invented name at a real address identifies nobody, which is the line this decision draws. One entry did cross it — "Yorkdale Tower Facilities" at "1 Yorkdale Rd" named a specific real building — and was changed.

The data shape. Values, margins, hours, crews and windows are untouched. What had to go was the identification, not the realism.

The guard, and why it is the load-bearing half

scripts/check-proof-copy.mjs had a removed-names check already. It went green on 6 August while three of the names it lists were still being served, because it read lib/customer-proof.ts and nothing else — the file somebody happened to edit last. A guard scoped to the site of the edit will always certify a removal that only happened at the site of the edit. It now walks app, components, lib and config, and it fails on all thirty-six names.

Comments are exempt per-file, and CHANGELOG.md, DECISIONS.md and docs/ are outside the scanned tree, for the reason already established in that script's header: a check that fires on the written explanation of a removal teaches the next person to remove things silently.

An enumerated list is a floor, not a ceiling — it catches the realistic regression, which is somebody restoring a fixture block from git history. The rule itself cannot be enumerated, so it is stated in prose directly above WorkOrder.client in lib/tenant-workspaces.ts, where a person writing a new fixture will read it: a fixture may describe anything and may name only Novel Systems.

When this is wrong

When a real organisation has been through docs/legal/CASE-STUDY-INTAKE.md and a consent artifact is committed to this repository. At that point the name goes in the guard's allow path and on the site, and the same bar applies that check three already applies to quotations: the permission is in the repo, readable by anyone reviewing this and producible later if anybody asks, or it does not ship.