Measured, not asserted
Published
A conflicts search is a membership question asked over normalised names. The intake team types what the client says; the register holds the legal name; a small table maps one onto the other. This test renamed that table and watched a firm open two matters adverse to its own current client, while the search reported -- accurately -- how many parties it had searched and how many conflicts it had found.
The search is not the hard part. The names are
Nobody types a company's registered name into an intake form. They type what the client said on the telephone. So every conflicts system carries a normalisation layer: a table mapping the spellings people use onto the names in the client register, and a set of edges linking each client to its affiliates, because acting against a subsidiary of your own client is still acting against your client.
The fixture is a small firm with two current clients, one of which has a German logistics affiliate, one waiver on file, and one lawyer screened off a named matter. Three proposed openings are measured. One names the intake spelling of a current client as an adverse party and must be refused. One names a current client for whom a waiver exists and may be opened. One names the affiliate and must be refused.
Alongside it sits the firm's only prohibition: an ethical wall. A screened lawyer must not reach a matter file even though the practice group he belongs to has a standing grant over it.
Protection on its own moved nothing
The base column for this pass was five areas across five presets: ES5, modern, the emit gate's own option set on both targets, and the string transforms. Twenty-five comparisons, twenty-five identical. Nothing below is caused by protecting the code.
The normalisation table, and two matters that should never have opened
With the alias table renamed, every name was compared exactly as the intake team typed it. The result was three matters OPEN, including both that should have been refused, and the firm's own search rule passed and reported search-check(searched 2, normalised 0, 0 hit(s)).
Read that sentence as a partner would. Two parties were searched. That is true. Nothing was found. That is also true. The search ran, it ran over the right number of parties, and it compared the wrong strings.
The detail that makes this worse than a dead screen: the waived matter still produced a hit, because its party name needed no normalisation. So the intake log shows the tool FINDING conflicts on the same run in which it missed two. A screen that returns nothing at all invites suspicion. A screen that returns something invites none.
The same result arrives from the other side. Renaming the client register produced zero hits everywhere -- but the configuration dump printed (empty -- the firm represents nobody), which is the kind of line somebody notices. The register is a thing people look at. The alias table is plumbing.
Losing the edges leaves a screen that half works
Renaming the field holding each client's affiliates -- the edges, not the register -- produced the most realistic outcome measured in this area. The direct conflict still fired and the matter adverse to the current client was refused. The matter adverse to that client's German affiliate was OPENED, with the check reporting searched 1, normalised 1, 0 hit(s).
Normalisation worked. The party name resolved correctly. There was simply nothing linking it to a client any more. A conflicts search that catches the obvious conflict and misses the corporate family is not a system anybody distrusts; it is a system that has been working all week.
The ethical wall is the one control whose loss reverses the answer
Everything else in this file weakens a decision. The wall inverts one. It exists to say that a screen defeats a practice-group grant, and a general access engine defaults the other way for the ordinary reason: it is written around grants, and a screen is something the firm adds.
With the flag that expresses that priority renamed, the screened lawyer was ALLOWED, and the record printed screened=true granted=true wall=yields. Every fact on that line is correct, including the fact that he is screened. The rule about what to do with those facts is the part that went missing.
Renaming the screen list instead produced the same access with screened=false. Same wrongful result, and this time the record does not even contain the contradiction. Two routes, one of which leaves the evidence on the page and one of which removes it -- which is the shape this series keeps finding, in a domain where the evidence is the point.
What failed loudly
Renaming the waiver table refused all three openings, including the one the firm is entitled to take. Renaming the adverse-party list produced no-parties(refused before search). The matter identifier produced unidentified-matter and the lawyer identifier unidentified-lawyer. Renaming the practice-group grants denied both access requests, including the legitimate one.
All of these are the cheap failures: an intake system that refuses every opening is discovered before lunch. The pinned control -- a label pinned equal to the library default on purpose -- measured identical, as predicted, for the twenty-fourth consecutive pass this prediction has held.
If you protect an intake or practice-management application
Make an unresolved name an error, not a pass. If the normalisation layer cannot map a party name onto anything in the register, the correct behaviour is to stop and ask a human, not to compare the raw string and report a clean search. That single change turns the quietest cell in this area into the loudest.
Assert the SEARCH SET, not the search. The check in this test counted parties and hits, and both counts were honest. A check that recorded which register entries the parties resolved to -- and refused when a party resolved to nothing -- would have refused both openings. Counting what you did tells you nothing about what you did it to.
And write the wall as a deny-by-default rule rather than a prohibition layered over grants. A rule whose meaning is lost should stop matching, not reverse. Our zero trust architecture guide covers the same principle at the application boundary.
Frequently asked questions
Did obfuscation change any conflicts result on its own?
No. Twenty-five base comparisons across five areas and five presets were all identical to the unprotected runs. Every failure here required member renaming aimed at a property name the installed conflicts engine also reads.
What happened when the alias table was renamed?
Every party name was compared exactly as typed at intake, so two adverse parties that should have matched the client register did not. All three proposed matters were reported OPEN, and the firm's search rule passed reporting two parties searched, none normalised, and no hits.
Would an empty search result look suspicious?
Not in this run. One matter still produced a hit, because its party name needed no normalisation, so the intake log showed the tool finding conflicts on the same run in which it missed two. A screen that returns nothing at all is easier to distrust than one that returns something.
What is the difference between renaming the register and renaming the aliases?
Both produce missed conflicts, but the register is visible. With the register renamed the configuration dump printed that the firm represents nobody, which somebody notices. The alias table is plumbing and its loss printed nothing at all.
What happened to the ethical wall?
The flag saying a screen defeats a practice-group grant reverts to the library default, which is the opposite rule. The screened lawyer was allowed in, and the access record printed that he was screened, that he was granted, and that the wall yields. Renaming the screen list instead allowed the same access while recording that he was not screened at all.
Which parts failed loudly?
Waivers, the adverse-party list, the matter identifier, the lawyer identifier and the practice-group grants all failed closed -- refused openings and denied access, including legitimate ones. Those are the failures a firm finds the same morning.
What is the cheapest fix?
Make a party name that resolves to nothing an error rather than a comparison, and assert which register entries the search actually resolved to instead of counting how many names it looked at. Both are worth doing regardless of obfuscation, because a dropped alias table produces exactly the same clean-looking search.
Related reading