feat: add contact redacted flag, placeholder detection, and country name/code resolution

- Add `redacted?: boolean` to `Contact`; set when any field was dropped as a placeholder, the name matches a privacy-service heuristic, or an RFC 9537 redaction targets that entity's role
- Add `isPlaceholderValue` to `privacy.ts` to identify boilerplate registrar strings (`"Please query the RDDS…"`, `"redacted"`, `"n/a"`, etc.) used in place of real email/phone/fax values; drop them from the contact during finalization
- Add `countries.ts` backed by `Intl.DisplayNames` (with a curated `ALIASES` table for common alternate names) providing `countryNameFromCode`, `countryCodeFromName`, and `resolveCountry`; a two-letter `country` value is now treated as a code and expanded to a full name
- Introduce `finalizeContact` in `contacts.ts` to centralise all contact post-processing (placeholder stripping, country resolution, `redacted` flag); call it from both RDAP and WHOIS normalizers
- Wire RFC 9537 redaction role-matching into `extractContacts` via a new `redactionTargetsRole` helper so entities targeted by a `redacted` entry automatically receive `redacted: true`
- Add `countries.test.ts` and extend RDAP/WHOIS normalizer tests to cover placeholder stripping, country fill-in, and redaction flag propagation
This commit is contained in:
2026-09-19 23:07:38 -04:00
parent 1d04be5c74
commit 89fa13ffef
10 changed files with 286 additions and 23 deletions
+2 -1
View File
@@ -553,7 +553,8 @@ interface DomainRecord {
state?: string;
postalCode?: string;
country?: string;
countryCode?: string;
countryCode?: string; // ISO 3166-1 alpha-2; country/countryCode are resolved from each other when possible
redacted?: boolean; // some contact data was redacted/withheld or replaced by a placeholder
}>;
privacyEnabled?: boolean; // registrant appears privacy-redacted based on name heuristics (privacy-service and redaction phrases) or RFC 9537 redactions
redactions?: Array<{