mirror of
https://github.com/jakejarvis/rdapper.git
synced 2026-10-26 08:26:22 -04:00
fix: stop flagging ordinary company names as privacy services
A weak word ("private", "protection") plus a generic context word ("services",
"contact") counted as a privacy service, so "Tata Consultancy Services Private
Limited" (the standard Indian company form), "Allied Fire Protection Services",
and "Contact Lens Protection Ltd" got privacyService/redacted/privacyEnabled.
"privado" and "for privacy" matched as substrings ("Banco Privado Atlántico",
"Center for Privacy and Technology").
Keep only domain-specific context words, ignore legal forms like "Private
Limited", "Pvt. Ltd.", and "Pte. Ltd.", and match Spanish services by phrase.
No change across the saved WHOIS corpus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2 files changed
+32
-10
No files matched your search
+18
-1
@@ -13,13 +13,30 @@ test("isPrivacyName flags redaction notices and privacy services", () => {
|
||||
"Identity Protection Service",
|
||||
"Withheld for Privacy ehf",
|
||||
"Datos Privados",
|
||||
"Contacto Privado",
|
||||
"Proxy Protection LLC",
|
||||
"Whois Privacy Services Pty Ltd",
|
||||
]) {
|
||||
expect(isPrivacyName(v), v).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
test("isPrivacyName does not flag ordinary names with ambiguous words", () => {
|
||||
for (const v of ["Private Equity Partners LLC", "Protection One", "Jane Private", "Acme Inc"]) {
|
||||
for (const v of [
|
||||
"Private Equity Partners LLC",
|
||||
"Protection One",
|
||||
"Jane Private",
|
||||
"Acme Inc",
|
||||
"Tata Consultancy Services Private Limited",
|
||||
"Endurance Domains Technology Pvt. Ltd.",
|
||||
"Example Holdings Pte. Ltd.",
|
||||
"Allied Fire Protection Services Inc",
|
||||
"Private Client Services Ltd",
|
||||
"Contact Lens Protection Ltd",
|
||||
"Banco Privado Atlantico",
|
||||
"Hospital Privado de Córdoba S.A.",
|
||||
"Center for Privacy and Technology",
|
||||
]) {
|
||||
expect(isPrivacyName(v), v).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
+14
-9
@@ -19,8 +19,10 @@ const REDACTION_PHRASES = [
|
||||
* redaction notices these can be real registrant text worth showing, so they aren't placeholders.
|
||||
*/
|
||||
const PRIVACY_SERVICE_PHRASES = [
|
||||
"privado", // Spanish
|
||||
"datos privados", // Spanish
|
||||
// Spanish; not "privado" alone, which names real banks, hospitals, and schools
|
||||
"datos privados",
|
||||
"contacto privado",
|
||||
"registro privado",
|
||||
"registration private",
|
||||
"private registration",
|
||||
"whois privacy",
|
||||
@@ -31,7 +33,6 @@ const PRIVACY_SERVICE_PHRASES = [
|
||||
"contact privacy",
|
||||
"domains by proxy",
|
||||
"proxy service",
|
||||
"for privacy",
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -41,7 +42,9 @@ export const PRIVACY_STRONG_KEYWORDS = [...REDACTION_PHRASES, ...PRIVACY_SERVICE
|
||||
|
||||
/**
|
||||
* Words too ambiguous to trust alone ("Private Equity LLC", "Protection One"). They only count
|
||||
* when at least two distinct terms from WEAK + CONTEXT appear as whole words.
|
||||
* when at least two distinct terms from WEAK + CONTEXT appear as whole words. Context words are
|
||||
* domain-specific: generic ones like "services" or "contact" turn up in ordinary company names
|
||||
* ("Allied Fire Protection Services", "Contact Lens Protection Ltd").
|
||||
*/
|
||||
const PRIVACY_WEAK_WORDS = ["privacy", "private", "protect", "protected", "protection"];
|
||||
const PRIVACY_CONTEXT_WORDS = [
|
||||
@@ -51,13 +54,14 @@ const PRIVACY_CONTEXT_WORDS = [
|
||||
"domains",
|
||||
"registration",
|
||||
"guard",
|
||||
"service",
|
||||
"services",
|
||||
"masked",
|
||||
"anonymous",
|
||||
"identity",
|
||||
"contact",
|
||||
];
|
||||
|
||||
// Legal forms containing a weak word: "Tata Consultancy Services Private Limited" (India),
|
||||
// "Example Pte. Ltd." (Singapore)
|
||||
const LEGAL_FORM_RE = /\(?\b(?:private|pvt|pte)\b\)?\.?\s*(?:limited|ltd)\b\.?/g;
|
||||
const WEAK_WORD_RE = new RegExp(`\\b(?:${PRIVACY_WEAK_WORDS.join("|")})\\b`, "g");
|
||||
const CONTEXT_WORD_RE = new RegExp(
|
||||
`\\b(?:${[...PRIVACY_WEAK_WORDS, ...PRIVACY_CONTEXT_WORDS].join("|")})\\b`,
|
||||
@@ -68,9 +72,10 @@ const CONTEXT_WORD_RE = new RegExp(
|
||||
export function isPrivacyName(value: string): boolean {
|
||||
const v = value.toLowerCase().trim();
|
||||
if (PRIVACY_STRONG_KEYWORDS.some((k) => v.includes(k))) return true;
|
||||
if (!WEAK_WORD_RE.test(v)) return false;
|
||||
const name = v.replace(LEGAL_FORM_RE, " ");
|
||||
WEAK_WORD_RE.lastIndex = 0;
|
||||
return new Set(v.match(CONTEXT_WORD_RE)).size >= 2;
|
||||
if (!WEAK_WORD_RE.test(name)) return false;
|
||||
return new Set(name.match(CONTEXT_WORD_RE)).size >= 2;
|
||||
}
|
||||
|
||||
const escapeRe = (v: string) => v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
|
||||
Reference in new issue
Block a user