@privacyscrubber/mcp-server 2.0.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ps-pii-engine.cjs CHANGED
@@ -1,4 +1,7 @@
1
1
  /**
2
+ * @generated by scripts/sync-pii-engine.js — DO NOT EDIT DIRECTLY
3
+ * Source of truth: src/core/pii-engine-core.js
4
+ *
2
5
  * PrivacyScrubber Shared PII Engine
3
6
  * Shared between Website Worker, Chrome Extension, and MCP Server.
4
7
  * Responsible for running Regex checks, overlap resolution, and reverse scrubbing.
@@ -31,14 +34,10 @@ let DEVOPS_SECRETS = [
31
34
  ];
32
35
 
33
36
  let REGEX_RULES = [
34
- ...DEVOPS_SECRETS,
35
37
  // Emails
36
38
  { type: 'EMAIL', regex: /\b[a-zA-Z0-9._%+-]{1,64}@[a-zA-Z0-9.-]{1,255}\.[a-zA-Z]{2,}\b/g },
37
39
 
38
- // Financial Data (PCI-DSS, Bank Accounts, Direct Deposits, Cards, IBAN, SWIFT, Routing Numbers)
39
- { type: 'FINANCIAL', regex: /\b[A-Z]{4}(?:AD|AE|AF|AG|AI|AL|AM|AO|AQ|AR|AS|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BJ|BL|BM|BN|BO|BQ|BR|BS|BT|BV|BW|BY|BZ|CA|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|CR|CU|CV|CW|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EE|EG|EH|ER|ES|ET|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|IO|IQ|IR|IS|IT|JE|JM|JO|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MF|MG|MH|MK|ML|MM|MN|MO|MP|MQ|MR|MS|MT|MU|MV|MW|MX|MY|MZ|NA|NC|NE|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|SS|ST|SV|SX|SY|SZ|TC|TD|TF|TG|TJ|TK|TL|TM|TN|TO|TR|TT|TV|TW|TZ|UA|UG|UM|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|YE|YT|ZA|ZM|ZW)[A-Z2-9][A-NP-Z0-9](?:[A-Z0-9]{3})?\b/g },
40
- { type: 'FINANCIAL', regex: /\b[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}[a-zA-Z0-9]{0,16}\b/g },
41
- { type: 'FINANCIAL', regex: /\bPORTFOLIO[-_][A-Z0-9]{5,}\b/gi },
40
+ // Financial Data (Cards, Crypto, Direct Deposit & Bank Routing)
42
41
  { type: 'FINANCIAL', regex: /\b(?:\d[ -]?){13,19}\b/g },
43
42
  { type: 'FINANCIAL', regex: /\b(?:1|3|bc1)[a-zA-HJ-NP-Z0-9]{25,39}\b/g },
44
43
  { type: 'FINANCIAL', regex: /\b0x[a-fA-F0-9]{40}\b/g },
@@ -46,45 +45,17 @@ let REGEX_RULES = [
46
45
  { type: 'FINANCIAL', regex: /\b(?:Account|Acct|Checking|Savings|Direct\s+Deposit)\s*(?:#|ID|No\.?|Number)?[:\s#]*(?:[\*xX•.-]{3,}\d{2,6}|\d{4}[-\s]?\d{4}[-\s]?\d{2,6})\b/gi },
47
46
  { type: 'FINANCIAL', regex: /\b(?:ABA|Routing|RTN)\s*(?:#|ID|No\.?|Number)?[:\s#]*\d{9}\b/gi },
48
47
 
49
- // Legal & Court
50
- { type: 'LEGAL', regex: /\bCASE[-_][A-Z0-9_-]{4,}\b/gi },
51
- { type: 'LEGAL', regex: /\bMATTER[-_][A-Z0-9_-]{4,}\b/gi },
52
- { type: 'PRIVILEGE', regex: /ATTORNEY[- ]CLIENT[- ]PRIVILEGE/gi },
53
-
54
48
  // Professional IDs & Organizations
55
- { type: 'NAME', isContextName: true, regex: /\b(?:[A-Z][A-Za-z0-9&.,'-]*[ \t\xA0]+){1,5}(?:Inc\.?|LLC|Corp\.?|Corporation|Ltd\.?|Limited|Co\.?|Company|Group|Holdings|Solutions|Services|Technologies|Logistics|Industries|Capital|Bank|Partners|LLP|PLLC)(?:\s+(?:LLC|Inc\.?|Corp\.?|Ltd\.?|USA|Group))?\b/g },
49
+ { type: 'NAME', isContextName: true, isCorporateName: true, regex: /\b(?:[A-Z][A-Za-z0-9&.,'-]*[ \t\xA0]+){1,5}(?:Inc\.?|LLC|Corp\.?|Corporation|Ltd\.?|Limited|Co\.?|Company|Group|Holdings|Solutions|Services|Technologies|Logistics|Industries|Capital|Bank|Partners|LLP|PLLC)(?:\s+(?:LLC|Inc\.?|Corp\.?|Ltd\.?|USA|Group))?\b/g },
56
50
  { type: 'ID', regex: /\b(?:Employee|Emp|EE|Worker|Staff|File|Badge|Member|Advisor|Producer|Agent|Borrower)\s*(?:#|ID|No\.?|Number)[:\s#]*[A-Z0-9-]{3,15}\b/gi },
57
- { type: 'ID', regex: /\b(?:Pay\s+Group|Cost\s+Center|Dept|Department)(?:[:#][\s#]*[A-Za-z0-9_-]{2,30}|\s+[A-Za-z0-9_-]*\d[A-Za-z0-9_-]*)\b/gi },
58
- { type: 'ID', regex: /(?:\b(?:Box\s+d\b|d\.\s*(?:Control|#)?|d\s+Control)\s*(?:number|no\.?|#|num)?[:\s#]*|\bControl\s*(?:number|no\.?|#|num)[:\s#]*|\bControl[:#]\s*)([A-Za-z0-9-]{3,30})/gi },
51
+ { type: 'ID', regex: /\b(?:Pay\s+Group[:#\s]+[A-Za-z0-9_-]{2,30}|(?:Cost\s+Center|Dept|Department)[:#\s]+[A-Za-z0-9_-]*\d[A-Za-z0-9_-]*)\b/gi },
52
+ { type: 'ID', regex: /(?:\b(?:Box\s+d\b|d\.\s*(?:Control|#)?|d\s+Control)\s*(?:Control\s+)?(?:number|no\.?|#|num)?[:\s#]+|\bControl\s*(?:number|no\.?|#|num)?[:\s#]+|\bControl[:#]\s*)([A-Za-z0-9-]{3,30})/gi },
59
53
  { type: 'ID', regex: /\bEEID[ -]?\d{4,}\b/gi },
60
- { type: 'ID', regex: /\bRESUME[-_]?[A-Z0-9]{4,}\b/gi },
61
- { type: 'ID', regex: /\bLEAD[-_][A-Z0-9]{5,}\b/gi },
62
- { type: 'ID', regex: /\bCAMPAIGN[-_][A-Z0-9]{4,}\b/gi },
63
- { type: 'ID', regex: /\bDEAL[-_][A-Z0-9]{4,}\b/gi },
64
- { type: 'ID', regex: /\bENTITY[-_][0-9]{4,}\b/gi },
65
- { type: 'ID', regex: /\bOPPORTUNITY[-_][A-Z0-9]{5,}\b/gi },
66
- { type: 'ID', regex: /\bPROSPECT[-_][A-Z0-9]{5,}\b/gi },
67
- { type: 'ID', regex: /\bTICKET[-_][A-Z0-9]{5,}\b/gi },
68
- { type: 'ID', regex: /\bZENDESK[-_][0-9]{4,}\b/gi },
69
54
  { type: 'ID', regex: /\bEMP[-_]\d{3,}\b/gi },
70
- { type: 'ID', regex: /\bLIS[-]?\d{6,}\b/gi },
71
- { type: 'ID', regex: /\bPARCEL[-]?\d{5,}\b/gi },
72
- { type: 'ID', regex: /\bAGENT[-_][A-Z0-9]{4,}\b/gi },
73
- { type: 'ID', regex: /\bTASK[-_][A-Z0-9]{5,}\b/gi },
74
- { type: 'ID', regex: /\bSTUDENT[-_][0-9]{5,}\b/gi },
75
- { type: 'ID', regex: /\bCOURSE[-_][A-Z0-9]{4,}\b/gi },
76
- { type: 'ID', regex: /\bINSTANCE[-_]ID[-_][a-z0-9-]{10,}\b/gi },
77
- { type: 'ID', regex: /\bENV[-_][A-Z0-9]{3,}\b/gi },
78
- { type: 'ID', regex: /\bTENANT[-_]ID[-_][0-9]{4,}\b/gi },
79
-
80
- // Insurance & Health Plan IDs
81
- { type: 'ID', regex: /\b(?:BCB|BCBS|AETNA|CIGNA|UHC|HUMANA|MEDICARE|MEDICAID)[-_A-Za-z0-9]+\b/gi },
82
- { type: 'ID', regex: /\b(?:Insurance\s+(?:ID|No\.?|Number|#)|Policy(?:\s*(?:ID|No\.?|Number|#)|[:#])|Member\s*(?:ID|No\.?|Number|#|[:#])|Subscriber\s*(?:ID|No\.?|Number|#|[:#])|Group\s*(?:ID|No\.?|Number|#|[:#])|Plan\s*(?:ID|No\.?|Number|#|[:#])|Health(?:\s+Plan)?\s*(?:ID|No\.?|Number|#)|Rx\s*(?:ID|No\.?|Number|Group|BIN|PCN|#))[:\s#]+([A-Za-z0-9-]{3,30})\b/gi },
83
- { type: 'ID', regex: /\b(?:Health\s+Plan(?:\s+Beneficiary)?|Beneficiary(?:\s+(?:No\.?|Number|ID|Num|#))?|HPN)[:\s#]+([A-Za-z0-9-]+)/gi },
84
- { type: 'ID', regex: /\bHPN[-_][A-Za-z0-9-]+\b/gi },
55
+
85
56
  { type: 'ADDRESS', isContextAddress: true, regex: /(?:(?:\bBox\s+f\b|\bf\.\s*|\bf\s+(?=Employee))\s*(?:Employee(?:'s)?\s*)?(?:address[,\s]+and\s+ZIP\s+code|address)?|(?:Employee(?:'s)?\s+address[,\s]+and\s+ZIP\s+code))[\s:#]*([A-Za-z0-9#.,\s-]{4,55}?)(?=\r?\n|$|\s{3,}|\t|Box|\d+\b|1\b|2\b|Wages|Federal|Social|Medicare)/gi },
86
57
  { type: 'ADDRESS', isContextAddress: true, regex: /(?:(?:Borrower(?:'s)?|Co-Borrower(?:'s)?|Employee(?:'s)?|Employer(?:'s)?|Home|Mailing|Property|Physical)\s+address)[\s:#]+([A-Za-z0-9#.,\s-]{4,55}?)(?=\r?\n|$|\s{3,}|\t|City|State|ZIP|SSN|EIN|Phone|Box|\d+\b)/gi },
87
- { type: 'ADDRESS', regex: /\b\d{1,6}[ \t\xA0]+(?:[A-Za-z0-9.-]+[ \t\xA0]+){0,4}(?:St|Street|Ave|Avenue|Blvd|Boulevard|Rd|Road|Ln|Lane|Dr|Drive|Way|Ct|Court|Pl|Place|Terrace|Pkwy|Parkway|Sq|Square|Hwy|Highway|Cir|Circle|Trl|Trail|Loop|Row|Pike|Bishopsgate|Gate|Walk|Close|Hill|Crescent|Gardens|Grove|Mews|Yard|Box|PO Box|P\.O\.[ \t\xA0]*Box)\b(?:[ \t\xA0]*,?[ \t\xA0]*(?:Apt|Apartment|Suite|Ste|Unit|#|Fl|Floor|Bldg|Building)\.?[ \t\xA0]*[A-Za-z0-9-]+)?/gi },
58
+ { type: 'ADDRESS', regex: /\b\d{1,6}[ \t\xA0]+(?:[A-Za-z0-9.-]+[ \t\xA0]+){0,4}(?:St|Street|Ave|Avenue|Blvd|Boulevard|Rd|Road|Ln|Lane|Dr|Drive|Way|Ct|(?<!District |Supreme |Circuit |Appellate |Bankruptcy |High |Federal |Trial )Court|Pl|Place|Terrace|Pkwy|Parkway|Sq|Square|Hwy|Highway|Cir|Circle|Trl|Trail|Loop|Row|Pike|Bishopsgate|Gate|Walk|Close|Hill|Crescent|Gardens|Grove|Mews|Yard|PO Box|P\.O\.[ \t\xA0]*Box)\b(?:[ \t\xA0]*,?[ \t\xA0]*(?:Apt|Apartment|Suite|Ste|Unit|#|Fl|Floor|Bldg|Building)\.?[ \t\xA0]*[A-Za-z0-9-]+)?/gi },
88
59
  { type: 'ADDRESS', regex: /\b(?:P\.?O\.?[ \t\xA0]*Box|PO[ \t\xA0]*Box)[ \t\xA0]+\d{1,6}\b/gi },
89
60
  { type: 'ADDRESS', regex: /\b[A-Za-z][a-zA-Z\s.-]{1,25},?\s+(?:AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY|DC|PR)\s+\d{5}(?:-\d{4})?\b/g },
90
61
  { type: 'ADDRESS', regex: /\b(?:ZIP|Postal|Code)?\s*(?:AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY|DC|PR)\s+\d{5}(?:-\d{4})?\b/g },
@@ -98,24 +69,7 @@ let REGEX_RULES = [
98
69
  { type: 'ID', regex: /\b[1-9][A-Za-z][0-9A-Za-z][0-9]-[A-Za-z][0-9A-Za-z][0-9]-[A-Za-z0-9]{4}\b/gi },
99
70
  { type: 'LOCATION', regex: /\b[A-Za-z][a-zA-Z .'-]{1,25},\s*(?:AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY|DC|PR)\b/g },
100
71
 
101
- // PHI & Medical
102
- { type: 'PHI', regex: /\b(?:MRN|Patient ID|Medical Record (?:No\.?|Num(?:ber)?|#)|Patient (?:No\.?|Num(?:ber)?|#))[\s:#]+([A-Za-z0-9-]+)/gi },
103
- { type: 'PHI', regex: /\bMRN[-_ ]*[A-Za-z0-9-]{4,}\b/gi },
104
- { type: 'ID', regex: /\b(?:NPI|National Provider Identifier)[:\s#]*(\d{10})\b/gi },
105
- { type: 'ID', regex: /\b(?:Device\s+(?:Identifier|ID|Serial|No\.?|Number)|UDI)[:\s#]+([A-Za-z0-9-]+)/gi },
106
- { type: 'ID', regex: /\bUDI[-_][A-Za-z0-9-]+\b/gi },
107
- { type: 'ID', regex: /\b(?:Vehicle\s+(?:Serial|ID|Identification(?:\s+Number)?|No\.?|Number)|VIN)[:\s#]+([A-Za-z0-9-]+)/gi },
108
- { type: 'PHI', regex: /\b(?!NCT|INC|SEC|ISO|DOC|SOC|CPT)[A-Z]{2,3}\d{6,8}\b/g },
109
- { type: 'PHI', regex: /\bNHS[ -]?\d{3}[ -]?\d{3}[ -]?\d{4}\b/gi },
110
-
111
- // Copyrights
112
- { type: 'COPYRIGHT', regex: /\bPROJECT[-_][A-Z0-9]{5,}\b/gi },
113
- { type: 'COPYRIGHT', regex: /\b(DRAFT|ASSET|SCRIPT)[-_][0-9]{4,}\b/gi },
114
-
115
72
  // General Privacy, Dates & Secrets
116
- { type: 'ID', regex: /\b(?:GDPR|HIPAA|CCPA|SOC2)[-_]AUDIT[-_]\d{4}\b/gi },
117
- { type: 'ID', regex: /\bPOLICY[-_][A-Z0-9]{5,}\b/gi },
118
- { type: 'ID', regex: /\bGRADE[S]?\s*:\s*[A-DF][+-]?\b/gi },
119
73
  { type: 'DATE', regex: /\b(?:DOB|BIRTHDAY|Date of Birth)[\s:]+([0-9./-]{6,10})\b/gi },
120
74
  { type: 'SECRET', regex: /\b(?:PASSWORD|PWD|SECRET)\s*[:=]\s*["']?[\S]{4,}["']?/gi },
121
75
 
@@ -138,7 +92,8 @@ let REGEX_RULES = [
138
92
  { type: 'ID', regex: /\b\d{2}\/\d{2}\/\d{4}\b/g },
139
93
 
140
94
  // Phone Numbers
141
- { type: 'PHONE', regex: /(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g },
95
+ { type: 'PHONE', regex: /(?<!\w)(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g },
96
+ { type: 'PHONE', regex: /\+\d{1,3}[ \t.-]+(?:\(?\d{1,4}\)?[ \t.-]+)?\d{2,8}(?:[ \t.-]+\d{2,8}){0,4}\b/g },
142
97
  { type: 'PHONE', regex: /\+?[1-9]\d{1,3}[\s.-]\(?\d{1,4}\)?[\s.-]\d{2,4}[\s.-]\d{4}/g },
143
98
  { type: 'PHONE', regex: /(?:\+44\s?7\d{3}|\(?07\d{3}\)?)\s?\d{3}\s?\d{3}\b/g },
144
99
  { type: 'PHONE', regex: /\b(?:\d{3}[-.\s]\d{4}|\(\d{3}\)\s??\d{3}[-.\s]??\d{4}|\d{3}[-.\s]??\d{3}[-.\s]??\d{4})\b/g },
@@ -164,6 +119,8 @@ let REGEX_RULES = [
164
119
  { type: 'NAME', regex: /(?<=^|[^\p{L}\p{N}_])\p{Lu}{2,}(?:[\p{Lu}'-]*\p{Lu})?(?:(?:[ \t\xA0]*\p{Lu}\.)+[ \t\xA0]*|[ \t\xA0]+)(?:\p{Lu}\p{Ll}[\p{Ll}'-]*|\p{Lu}[\p{Ll}'-]*[\p{Lu}'-][\p{Ll}'-]*)(?:'s)?(?=[^\p{L}\p{N}_]|$)(?![ \t\xA0]*:)/gu },
165
120
  // Names with Honorifics (with or without period, supporting single or multi-word full names) (Unicode-safe)
166
121
  { type: 'NAME', regex: /(?<=^|[^\p{L}\p{N}_])(?:Mr|Mrs|Ms|Dr|Prof|Hon|Mr\.|Mrs\.|Ms\.|Dr\.|Prof\.|Hon\.)[ \t\xA0]+(?:\p{Lu}[\p{Ll}'-]*\p{Ll}|\p{Lu}[\p{Ll}'-]*[\p{Lu}'-][\p{Ll}'-]*)(?:[ \t\xA0]+(?:\p{Lu}[\p{Ll}'-]*\p{Ll}|\p{Lu}[\p{Ll}'-]*[\p{Lu}'-][\p{Ll}'-]*))?(?=[^\p{L}\p{N}_]|$)(?![ \t\xA0]*:)/gu },
122
+ // Names with Quoted or Parenthetical Nicknames (e.g. Judith "Judy" Diaz, Robert (Bob) Smith)
123
+ { type: 'NAME', regex: /(?<=^|[^\p{L}\p{N}_])(?:\p{Lu}[\p{Ll}'-]+)[ \t\xA0]+(?:"[\p{Lu}\p{Ll}'-]+"|'[\p{Lu}\p{Ll}'-]+'|[“‘][\p{Lu}\p{Ll}'-]+[”’]|\([\p{Lu}\p{Ll}'-]+\))[ \t\xA0]+(?:\p{Lu}[\p{Ll}'-]+)(?:'s)?(?=[^\p{L}\p{N}_]|$)(?![ \t\xA0]*:)/gu },
167
124
 
168
125
  // W-2 Box c Employer Block (Name, Address, and Zip Code)
169
126
  { type: 'NAME', isContextName: true, regex: /(?:(?:\bBox\s+c\b|\bc\.\s*|\bc\s+(?=Employer))\s*(?:Employer(?:'s)?\s*)?(?:name[,\s]+address[,\s]+and\s+ZIP\s+code|name)?|(?:Employer(?:'s)?\s+name[,\s]+address[,\s]+and\s+ZIP\s+code))[\s:#]*([A-Za-z0-9&., \t\xA0'-]{2,45}?)(?=\r?\n|$|\s{3,}|\t|EIN|FEIN|Box|\d+\b|Wages|Federal|Social|Medicare)/gi },
@@ -174,7 +131,11 @@ let REGEX_RULES = [
174
131
  // Contextual Last Names (Last name, Surname, Family name)
175
132
  { type: 'NAME', isContextName: true, regex: /(?:(?:Employee(?:'s)?|Borrower(?:'s)?|Co-Borrower(?:'s)?|Applicant(?:'s)?|Candidate(?:'s)?|Worker(?:'s)?|Taxpayer(?:'s)?|Spouse(?:'s)?|Person(?:'s)?)\s+)?(?:Last\s+name|Surname|Family\s+name)[\s:#]+(?:\b|\b\s*)([A-Za-z'-]{2,30})/gi },
176
133
  // Contextual General Names (Employee, Principal Investigator, Physician, Doctor, etc.)
177
- { type: 'NAME', isContextName: true, regex: /(?:(?:Employee|Employer|Borrower|Co-Borrower|Applicant|Candidate|Worker|Taxpayer|Spouse|Client|Customer|Patient|Claimant|Insured|Tenant|Landlord|Buyer|Seller|Plaintiff|Defendant|Testator|Author)\s+(?:Name|Full\s+Name)|(?:Principal\s+Investigator|Investigator|Physician|Doctor|Supervisor|Reporting\s+To|Prepared\s+By|Attention|Attn|Contact(?:\s+Person)?|Author)(?:\s+Name)?|(?:Employee|Employer|Borrower|Client|Customer|Patient|Claimant|Insured|Doctor|Attn|Signatory|Witness|Tenant|Landlord|Buyer|Seller|Plaintiff|Defendant|Author)\s*[:=#])[:\s#]*(?:\b|\b\s*)([A-Z\p{Lu}][A-Za-z0-9&.,\s'-]{1,35}?)(?=\r?\n|$|\s{3,}|\t|Employee|Employer|Address|Phone|SSN|EIN|FEIN|Date|Pay|Rate|Tax|W-2|OMB|Copy|Box|Status)/giu },
134
+ { type: 'NAME', isContextName: true, regex: /(?:(?:Employee|Employer|Borrower|Co-Borrower|Applicant|Candidate|Worker|Taxpayer|Spouse|Client|Customer|Patient|Claimant|Insured|Tenant|Landlord|Buyer|Seller|Plaintiff|Defendant|Testator|Author)\s+(?:Name|Full\s+Name)|(?:Principal\s+Investigator|Investigator|Physician|Doctor|Supervisor|Reporting\s+To|Prepared\s+By|Attention|Attn|(?<!Emergency\s+|ICE\s+)Contact(?:\s+Person)?|Author)(?:\s+Name)?|(?:Employee|Employer|Borrower|Client|Customer|Patient|Claimant|Insured|Doctor|Attn|Signatory|Witness|Tenant|Landlord|Buyer|Seller|Plaintiff|Defendant|Author)\s*[:=#])[:\s#|]*(?:\b|\b\s*)([A-Z\p{Lu}][A-Za-z0-9&.,\s'"“”()-]{1,35}?)(?=\r?\n|$|\s{3,}|\t|Employee|Employer|Address|Phone|SSN|EIN|FEIN|Date|Pay|Rate|Tax|W-2|OMB|Copy|Box|Status|\|)/giu },
135
+ // Contextual Nicknames & Preferred Names (e.g. "Nickname: Judy", "Preferred Name: Alex", "AKA: Bob", "Goes by: Sam")
136
+ { type: 'NAME', isContextName: true, regex: /(?:(?:Patient(?:'s)?|Client(?:'s)?|Child(?:'s)?|Employee(?:'s)?|Person(?:'s)?)\s+)?(?:Nickname|Nick\s+Name|Preferred\s+(?:First\s+)?Name|Also\s+Known\s+As|AKA|Alias|Goes\s+by)[\s:#]+(?:\b|\b\s*)([A-Z\p{Lu}][A-Za-z0-9&.,\s'-]{1,30}?)(?=\r?\n|$|\s{3,}|\t|DOB|Date|Phone|Address|Emergency|Relationship|Notes|MRN|\()/giu },
137
+ // Emergency Contacts (Standard, Inverted Last First, Single Name, Table Cells, Extended Relationships, Brackets & Phone Lookahead)
138
+ { type: 'NAME', isContextName: true, regex: /(?:(?:^|[^\p{L}\p{N}_]|\|)\s*(?:In\s+Case\s+of\s+Emergency(?:\s*\(ICE\))?|ICE(?:[ \t\xA0]*(?:Contact|Notification|Person|Name))?|Emergency(?:[ \t\xA0]*(?:Contact|Notification|Person|Info|Details))?|Primary\s+Emergency\s+Contact|Secondary\s+Emergency\s+Contact|Alternate\s+Emergency\s+Contact|Person\s+to\s+notify\s+(?:in\s+case\s+of\s+emergency|in\s+emergency))(?:[ \t\xA0]*(?:[12#]|#\s*\d|\(\d\)))?(?:[ \t\xA0]*(?:Person|Name|Full\s+Name))?(?:[ \t\xA0]*(?:[\/&+-]|and)[ \t\xA0]*(?:Relationship|Relation|Proxy|Guarantor|Guardian))?(?:[ \t\xA0]*\((?:Primary|Secondary|Name|Relationship|Relation|Proxy|Guarantor|Legal\s+Guardian|Full\s+Name)\))?)[:=#|\/\t\s-]*[:=#|\/\t-][ \t\xA0]*([A-Z\p{Lu}][A-Za-z0-9&.'’]*(?:[ \t\xA0]+[A-Za-z0-9&.'’]+)*(?:,[ \t\xA0]*(?!(?:Relationship|Relation|Rel|Mother|Father|Spouse|Wife|Husband|Partner|Son|Daughter|Child|Parent|Brother|Sister|Sibling|Friend|Aunt|Uncle|Cousin|Guardian|Caregiver|Carer|Neighbor|Relative|Family|Grandmother|Grandfather|Grandparent|Grandson|Granddaughter|Stepmother|Stepfather|Stepson|Stepdaughter|Step-mother|Step-father|In-law|Mother-in-law|Father-in-law|Sister-in-law|Brother-in-law|Son-in-law|Daughter-in-law|Fiancé|Fiance|Fiancee|Significant\s+Other|Domestic\s+Partner|Life\s+Partner|Roommate|Colleague|Coworker|Co-worker|Legal\s+Guardian|Case\s+Worker|Caseworker|Social\s+Worker|Foster\s+Parent|POA|Power\s+of\s+Attorney|Healthcare\s+Proxy|Medical\s+Proxy|Proxy|Next\s+of\s+Kin|Aide)\b)[A-Z\p{Lu}][A-Za-z0-9&.'’]*(?:[ \t\xA0]+[A-Za-z0-9&.'’]+)*)?)(?=[ \t\xA0]*(?:\([A-Za-z0-9\s\/&':.+–-]+\)|\[[A-Za-z0-9\s\/&':.+–-]+\]|\{[A-Za-z0-9\s\/&':.+–-]+\}|[,\/|\-–—]{1,3}\s*(?:Relationship|Relation|Rel|Mother|Father|Spouse|Wife|Husband|Partner|Son|Daughter|Child|Parent|Brother|Sister|Sibling|Friend|Aunt|Uncle|Cousin|Guardian|Caregiver|Carer|Neighbor|Relative|Family|Grandmother|Grandfather|Grandparent|Grandson|Granddaughter|Stepmother|Stepfather|Stepson|Stepdaughter|Step-mother|Step-father|In-law|Mother-in-law|Father-in-law|Sister-in-law|Brother-in-law|Son-in-law|Daughter-in-law|Fiancé|Fiance|Fiancee|Significant\s+Other|Domestic\s+Partner|Life\s+Partner|Roommate|Colleague|Coworker|Co-worker|Legal\s+Guardian|Case\s+Worker|Caseworker|Social\s+Worker|Foster\s+Parent|POA|Power\s+of\s+Attorney|Healthcare\s+Proxy|Medical\s+Proxy|Proxy|Next\s+of\s+Kin|Aide)\b|[,\/|\-–—]?[ \t\xA0]*(?:Phone|Tel|Cell|Mobile|Work|Home|Office|Direct|Telephone)[:\s#-]*|[,\/|\-–—]?[ \t\xA0]*(?:Relationship|Relation|Rel)[:\s#-]*|[,\/|\-–—]?[ \t\xA0]*(?:\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b|[,\/|\-–—]?[ \t\xA0]*\d{3}[-.\s]?\d{4}\b|[ \t\xA0]*(?:\||\r?\n|$|\s{2,}|\t)))/gui },
178
139
  // Box e shorthand
179
140
  { type: 'NAME', isContextName: true, regex: /\b(?:Box\s+e)\s*[:#-]\s*([A-Za-z0-9&.,\s'-]{2,40})/gi }
180
141
  ];
@@ -185,28 +146,55 @@ let PROFILE_RULES = {
185
146
  { type: 'LEGAL', regex: /\bCASE[-_][A-Z0-9_-]{4,}\b/gi },
186
147
  { type: 'LEGAL', regex: /\bMATTER[-_][A-Z0-9_-]{4,}\b/gi },
187
148
  { type: 'LEGAL', regex: /\b[A-Z]{2,4}[- ]?\d{2}[- ]?\d{4,}\b/g },
188
- { type: 'PRIVILEGE', regex: /ATTORNEY[- ]CLIENT[- ]PRIVILEGE/gi }
149
+ { type: 'PRIVILEGE', regex: /ATTORNEY[- ]CLIENT[- ]PRIVILEGE/gi },
150
+ { type: 'LEGAL', regex: /\b(?:BATES|PROD|PLTF|DEFT|CONF|EXHIBIT)[-_ ]?[A-Z0-9]{2,10}[-_ ]?\d{4,10}\b/gi },
151
+ { type: 'LEGAL', regex: /\b(?:\d{1,2}:)?\d{2,4}[-_ ]?(?:CV|CR|MDL|BK|MC|MISC|MJ|PO|CA|AP|PR)[-_ ][A-Z0-9_-]{3,15}\b/gi },
152
+ { type: 'ID', regex: /\b(?:STATE\s+BAR|BAR\s+(?:NO\.?|#|ID)|SBN|ATTORNEY\s+REG(?:ISTRATION)?)[:\s#-]*\d{4,8}\b/gi },
153
+ { type: 'LEGAL', regex: /\b(?:RETAINER|ENGAGEMENT|REPRESENTATION)[-_: ]*(?:AGREEMENT|ID|REF)?[:\s#-]*[A-Z0-9_-]{4,20}\b/gi },
154
+ { type: 'LEGAL', regex: /\bECLI:[A-Z]{2}:[A-Za-z0-9]{1,7}:\d{4}:[A-Za-z0-9.]{1,25}\b/g },
155
+ { type: 'ID', regex: /\bPCT\/[A-Z]{2}\d{4}\/\d{6}\b/g },
156
+ { type: 'ID', regex: /\b(?:TX|TXu|VA|VAu|PA|PAu|SR|SRu|SE|SEu|RE)\s*-?\d[-\d ]{5,9}\d\b/g }
189
157
  ],
190
158
  hr: [
191
159
  { type: 'NAME', isContextName: true, regex: /(?:Candidate|Applicant|Employee|Reporting To|Manager|Mentored by|Direct Report)[\s:]+([A-Z][a-z]*(?:\s+[A-Z][a-z]*)?)/g },
192
160
  { type: 'ID', regex: /\bEEID[ -]?\d{4,}\b/gi },
193
161
  { type: 'ID', regex: /\bEMP[-_]\d{3,}\b/gi },
194
162
  { type: 'ID', regex: /\bRESUME[-_]?[A-Z0-9]{4,}\b/gi },
163
+ { type: 'ID', regex: /\b(?:CAND|CANDIDATE|APPLICANT)[-_: ]+[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
164
+ { type: 'ID', regex: /\b(?:WKDY|WORKDAY)[-_: ]+[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
165
+ { type: 'ID', regex: /\b(?:WORKS\s+COUNCIL|BETRIEBSRAT)(?:\s+(?:REF|ID|NOTICE))?[:\s#-]*[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
166
+ { type: 'ID', regex: /\bPIP[-_: ]+[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
167
+ { type: 'ID', regex: /\b(?:SECURITY\s+)?BADGE[:\s#-]*\d{4,8}\b/gi },
195
168
  { type: 'DATE', regex: /\b(?:DOB|BIRTHDAY|Date of Birth)[\s:]+([0-9./-]{6,10})\b/gi },
196
169
  { type: 'DATE', regex: /\b(?:Graduated|Graduation|Class of)[:\s]+(?:(?:Spring|Summer|Fall|Winter)\s+)?(?:(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|January|February|March|April|June|July|August|September|October|November|December)\s+)?\d{4}\b/gi },
197
170
  { type: 'ID', regex: /(?:https?:\/\/)?(?:www\.)?linkedin\.com\/in\/[A-Za-z0-9_-]+/gi },
198
171
  { type: 'ID', regex: /(?:https?:\/\/)?(?:www\.)?github\.com\/[A-Za-z0-9_-]+/gi },
199
- { type: 'ADDRESS', regex: /\b\d{1,6}\s+(?:[A-Z0-9][a-zA-Z0-9-]*\s+){1,3}(?:St|Street|Ave|Avenue|Blvd|Boulevard|Rd|Road|Ln|Lane|Drive|Way|Ct|Court|Pl|Place|Terrace|Pkwy|Parkway|Sq|Square|Highway|Hwy|Circle|Cir|Trail|Trl|Dr(?!\.?\s+[A-Z][a-z]+))\b/g }
172
+ { type: 'ADDRESS', regex: /\b\d{1,6}\s+(?:[A-Z0-9][a-zA-Z0-9-]*\s+){1,3}(?:St|Street|Ave|Avenue|Blvd|Boulevard|Rd|Road|Ln|Lane|Drive|Way|Ct|(?<!District |Supreme |Circuit |Appellate |Bankruptcy |High |Federal |Trial )Court|Pl|Place|Terrace|Pkwy|Parkway|Sq|Square|Highway|Hwy|Circle|Cir|Trail|Trl|Dr(?!\.?\s+[A-Z][a-z]+))\b/g },
173
+ { type: 'ID', regex: /\b(?:AOID|Associate\s+ID)[:\s#]*([A-Z0-9]{8,12})\b/gi },
174
+ { type: 'ID', regex: /\b(?:E-Verify\s*(?:Case|Verification)?\s*(?:No\.?|#|Number)?)[:\s#]*(\d{12,15})\b/gi },
175
+ { type: 'ID', regex: /\b(?:EEOC\s*(?:Charge|Case)?\s*(?:No\.?|#|Number)?)[:\s#-]*(\d{2,3}-\d{4}-\d{5})\b/gi },
176
+ { type: 'ID', regex: /\b(?:A-?Number|USCIS\s*(?:#|No\.?))[:\s#]*(?:A[- ]?)?(\d{9})\b/gi }
200
177
  ],
201
178
  finance: [
202
179
  { type: 'FINANCIAL', regex: /\b[A-Z]{4}(?:AD|AE|AF|AG|AI|AL|AM|AO|AQ|AR|AS|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BJ|BL|BM|BN|BO|BQ|BR|BS|BT|BV|BW|BY|BZ|CA|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|CR|CU|CV|CW|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EE|EG|EH|ER|ES|ET|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|IO|IQ|IR|IS|IT|JE|JM|JO|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MF|MG|MH|MK|ML|MM|MN|MO|MP|MQ|MR|MS|MT|MU|MV|MW|MX|MY|MZ|NA|NC|NE|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|SS|ST|SV|SX|SY|SZ|TC|TD|TF|TG|TJ|TK|TL|TM|TN|TO|TR|TT|TV|TW|TZ|UA|UG|UM|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|YE|YT|ZA|ZM|ZW)[A-Z2-9][A-NP-Z0-9](?:[A-Z0-9]{3})?\b/g },
203
180
  { type: 'FINANCIAL', regex: /\b[A-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}[a-zA-Z0-9]{0,16}\b/g },
204
- { type: 'FINANCIAL', regex: /\bPORTFOLIO[-_][A-Z0-9]{5,}\b/gi }
181
+ { type: 'FINANCIAL', regex: /\bPORTFOLIO[-_][A-Z0-9_-]{5,}\b/gi },
182
+ { type: 'FINANCIAL', regex: /\b(?:Account|Acct|Brokerage|IRA|401k|403b|Roth|Trust|Custodial|Portfolio)\s*(?:Number|Num|No\.?|#)?[:\s#]+(?!GL[-_])([A-Za-z0-9-]{6,20})\b/gi },
183
+ { type: 'ID', regex: /\bCUSIP[:\s#]*([0-9A-Z]{9})\b/gi },
184
+ { type: 'ID', regex: /\bISIN[:\s#]*([A-Z]{2}[0-9A-Z]{9}[0-9])\b/gi },
185
+ { type: 'ID', regex: /\bSEDOL[:\s#]*([0-9B-DF-HJ-NP-TV-Z]{6}[0-9])\b/gi },
186
+ { type: 'FINANCIAL', regex: /\b(?:Routing|ABA|Transit)\s*(?:Number|Num|No\.?|#)?[:\s#]+(\d{9})\b/gi },
187
+ { type: 'ID', regex: /\b(?:FEIN|EIN|TIN|Tax\s*ID)[:\s#]*(\d{2}-\d{7})\b/gi },
188
+ { type: 'ID', regex: /\b(?:CRD|CIK|Advisor\s*ID|Broker\s*ID)[:\s#]*(\d{5,10})\b/gi },
189
+ { type: 'ID', regex: /\b(?:LEI|LEGAL[\s-]ENTITY[\s-]IDENTIFIER)[:\s#-]*[0-9A-Z]{20}\b/gi },
190
+ { type: 'ID', regex: /\bBBG[0-9A-Z]{9}\b/g },
191
+ { type: 'FINANCIAL', regex: /(?<=\b(?:Wire(?:\s+(?:Transfer|Amount))?|Transfer|Balance|Deposit|Withdrawal|Settlement|Principal|Interest|Remittance|Payout|Transaction(?:\s+Amount)?|Payment(?:\s+Amount)?|Total|Amount)[:\s]+)(?:(?:\b(?:USD|EUR|GBP|CHF|ILS|RUB)\s*|[$€£¥₪₽₹]\s*)[0-9,.'’]*\d[KMB]?\b|\b\d[0-9,.'’]*\d?[KMB]?\s*(?:\b(?:USD|EUR|GBP|CHF|ILS|RUB)\b|[$€£¥₪₽₹])|[0-9,.'’]{3,}\b)/gi },
192
+ { type: 'FINANCIAL', regex: /(?:(?:\b(?:USD|EUR|GBP|CHF|ILS|RUB)\s*|[$€£¥₪₽₹]\s*)[0-9,.'’]*\d[KMB]?\b|\b\d[0-9,.'’]*\d?[KMB]?\s*(?:\b(?:USD|EUR|GBP|CHF|ILS|RUB)\b|[$€£¥₪₽₹]))/gi }
205
193
  ],
206
194
  medical: [
207
195
  { type: 'PHI', regex: /\b(?:MRN|Patient ID|Medical Record (?:No\.?|Num(?:ber)?|#)|Patient (?:No\.?|Num(?:ber)?|#))[\s:#]+([A-Za-z0-9-]+)/gi },
208
196
  { type: 'DATE', regex: /\b(?:DOB|Date of Birth|BIRTHDAY)[\s:]+([0-9./-]{6,10})\b/gi },
209
- { type: 'PHI', regex: /\bMRN[-_ ]*[A-Za-z0-9-]{4,}\b/gi },
197
+ { type: 'PHI', regex: /\bMRN[-_ ]*[A-Za-z0-9_-]{4,}\b/gi },
210
198
  { type: 'ID', regex: /\b(?:Insurance\s+(?:ID|No\.?|Number|#)|Policy(?:\s*(?:ID|No\.?|Number|#)|[:#])|Member\s*(?:ID|No\.?|Number|#|[:#])|Subscriber\s*(?:ID|No\.?|Number|#|[:#])|Group\s*(?:ID|No\.?|Number|#|[:#])|Plan\s*(?:ID|No\.?|Number|#|[:#])|Health(?:\s+Plan)?\s*(?:ID|No\.?|Number|#)|Rx\s*(?:ID|No\.?|Number|Group|BIN|PCN|#))[:\s#]+([A-Za-z0-9-]{3,30})\b/gi },
211
199
  { type: 'ID', regex: /\b(?:Health\s+Plan(?:\s+Beneficiary)?|Beneficiary(?:\s+No\.?|\s+Number)?|HPN)[:\s#]+([A-Za-z0-9-]+)/gi },
212
200
  { type: 'ID', regex: /\bHPN[-_][A-Za-z0-9-]+\b/gi },
@@ -217,136 +205,265 @@ let PROFILE_RULES = {
217
205
  { type: 'ID', regex: /\b(?:Vehicle\s+(?:Serial|ID|Identification(?:\s+Number)?|No\.?|Number)|VIN)[:\s#]+([A-Za-z0-9-]+)/gi },
218
206
  { type: 'ID', regex: /\bVIN[-_][A-Za-z0-9-]+\b/gi },
219
207
  { type: 'PHI', regex: /\b(?!NCT|INC|SEC|ISO|DOC|SOC|CPT)[A-Z]{2,3}\d{6,8}\b/g },
220
- { type: 'PHI', regex: /\bNHS[ -]?\d{3}[ -]?\d{3}[ -]?\d{4}\b/gi }
208
+ { type: 'PHI', regex: /\bNHS[ -]?\d{3}[ -]?\d{3}[ -]?\d{4}\b/gi },
209
+ { type: 'ID', regex: /\b(?:DEA|DEA\s*(?:#|No\.?|Number|Reg(?:istration)?))[:\s#]*([A-Z][A-Z9]\d{7})\b/gi },
210
+ { type: 'PHI', regex: /\b(?:CHI|CHI\s*(?:No\.?|Number|#))[:\s#]*(\d{10})\b/gi },
211
+ { type: 'DATE', regex: /\b(?:Admission|Admit|Discharge|Service|DOS|Encounter|Death)\s*Date[:\s]+([0-9.\/-]{6,10})\b/gi },
212
+ { type: 'ID', regex: /\b(?:Patient|Encounter|Practitioner|Observation|Condition|Procedure|MedicationRequest|DiagnosticReport)\/[A-Za-z0-9\-.]{1,64}\b/g }
221
213
  ],
222
214
  security: [
223
- { type: 'SECRET', regex: /\b(?:INCIDENT|BREACH)[-_: ]?ID[-_: ]?[0-9]{4,10}\b/gi }
215
+ ...DEVOPS_SECRETS,
216
+ { type: 'SECRET', regex: /\b(?:INCIDENT|BREACH)[-_: ]?ID[-_: ]?[0-9]{4,10}\b/gi },
217
+ { type: 'ID', regex: /\b(?:APT|UNC|FIN|TA|LAPSUS\$|DEV|Storm)[-_ ]?\d{1,4}\b/gi },
218
+ { type: 'ID', regex: /\b(?:TA|T|M|G|S|C|DS)\d{4}(?:\.\d{3})?\b/g },
219
+ { type: 'SECRET', regex: /\bCVE-(?:1999|20\d{2})-\d{4,7}\b/gi },
220
+ { type: 'ID', regex: /\bCWE-\d{1,5}\b/gi },
221
+ { type: 'SECRET', regex: /\b(?:SIGMA|SPLUNK|ELK|QRADAR|SURICATA|SNORT)[-_ ]*(?:RULE|SIG|ID)?[:\s_-]*[A-Z0-9_-]{4,25}\b/gi },
222
+ { type: 'SECRET', regex: /\b(?:FW|FIREWALL|ACL|POLICY)[-_ ]*(?:RULE|SESSION|ID)[:\s#-]*[A-Za-z0-9_-]{4,25}\b/gi },
223
+ { type: 'SECRET', regex: /\b(?:sha256|SHA256)[:\s=]+[a-fA-F0-9]{64}\b/gi },
224
+ { type: 'SECRET', regex: /\b(?:md5|MD5)[:\s=]+[a-fA-F0-9]{32}\b/gi },
225
+ { type: 'SECRET', regex: /\b(?:sha1|SHA1)[:\s=]+[a-fA-F0-9]{40}\b/gi },
226
+ { type: 'SECRET', regex: /-----BEGIN OPENSSH PRIVATE KEY-----/g },
227
+ { type: 'SECRET', regex: /\b(?:GHSA|USN|RHSA|ALAS|VMSA|MS)[-_ ]?\d{2,4}[-_ ][A-Za-z0-9_-]{1,12}\b/gi },
228
+ { type: 'ID', regex: /\bhxxps?:\/\/[^\s"']+\b/gi },
229
+ { type: 'ID', regex: /\bCVSS:(?:3\.[01]|4\.0)\/[A-Z0-9:\/._ -]+\b/gi }
230
+ ],
231
+ dev: [
232
+ ...DEVOPS_SECRETS,
233
+ { type: 'SECRET', regex: /\b(?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|amqp|mssql):\/\/[^\s"']+/gi },
234
+ { type: 'SECRET', regex: /\b(?:ghp|gho|ghu|ghs|ghr|glpat|npm|xox[baprs])[-_][A-Za-z0-9_-]{10,}\b/g },
235
+ { type: 'SECRET', regex: /\b(?:[rs]k)_(?:test|live)_[a-zA-Z0-9]{14,}\b/g },
236
+ { type: 'SECRET', regex: /\b(?:whsec|webhook[-_]secret|signing[-_]secret)[-_: =]*[a-zA-Z0-9_-]{16,}\b/gi },
237
+ { type: 'SECRET', regex: /\bBearer\s+eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\b/gi },
238
+ { type: 'SECRET', regex: /-----BEGIN (?:RSA |EC |PGP |DSA |OPENSSH )?PRIVATE KEY-----/g },
239
+ { type: 'IP', regex: /\b(?:(?:10\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])|192\.168)\.\d{1,3}\.\d{1,3}|localhost):\d{2,5}\b/g },
240
+ { type: 'SECRET', regex: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g },
241
+ { type: 'SECRET', regex: /\bAIza[0-9A-Za-z\-_]{35}\b/g },
242
+ { type: 'SECRET', regex: /\bsk-ant-(?:api03|admin01)-[a-zA-Z0-9_\-]{80,}\b/g },
243
+ { type: 'SECRET', regex: /\bsk-(?:proj-|admin-)?[a-zA-Z0-9_\-]{48,164}\b/g },
244
+ { type: 'SECRET', regex: /\bSG\.[a-zA-Z0-9_\-]{22}\.[a-zA-Z0-9_\-]{43}\b/g },
245
+ { type: 'SECRET', regex: /\b(?:AC|SK)[0-9a-fA-F]{32}\b/g },
246
+ { type: 'SECRET', regex: /\bhv[sbr]\.[a-zA-Z0-9_-]{24,96}\b/g },
247
+ { type: 'SECRET', regex: /\bdckr_pat_[a-zA-Z0-9_\-]{27,36}\b/g }
224
248
  ],
225
249
  marketing: [
226
250
  { type: 'ID', regex: /\b(?:LEAD|PROSPECT)[-_: ]*[A-Z0-9_-]*[0-9][A-Z0-9_-]*\b/gi },
227
251
  { type: 'ID', regex: /\b(?:CAMPAIGN|CLID|GCLID|FBCLID)[-_:=]*[A-Za-z0-9_-]{10,}\b/gi },
228
- { type: 'FINANCIAL', regex: /(?<=\b(?:LTV|CAC)[\s:]*)(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[0-9,.]+\b/gi },
229
- { type: 'ID', regex: /\b(?:SEGMENT|COHORT)[-_: ]*[0-9]{4,8}\b/gi }
252
+ { type: 'FINANCIAL', regex: /(?<=\b(?:LTV|CAC)[\s:]*)(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[0-9,.'’]+\b/gi },
253
+ { type: 'ID', regex: /\b(?:SEGMENT|COHORT)[-_: ]*[0-9]{4,8}\b/gi },
254
+ { type: 'ID', regex: /\b(?:G-[A-Z0-9]{8,12}|UA-\d{4,10}-\d{1,4})\b/g },
255
+ { type: 'ID', regex: /\b(?:MARKETO|PARDOT|KLAVIYO|HUBSPOT_CONTACT)[-_ ]*(?:LEAD|ID)?[:\s#-]*[A-Za-z0-9_-]{6,25}\b/gi },
256
+ { type: 'ID', regex: /(?:\?|&)(?:utm_source|utm_medium|utm_campaign|utm_term|utm_content)=([^&\s#"']+)/gi },
257
+ { type: 'ID', regex: /\b(?:_?ga=)?(?:GA\d\.\d\.)?(\d{9,10}\.\d{9,10})\b/g }
230
258
  ],
231
259
  bizops: [
232
- { type: 'ID', regex: /\b(?:DEAL|KPI|METRIC)[-_: ]?[A-Z0-9]{4,}\b/gi },
233
- { type: 'ID', regex: /\b(?:ENTITY|VENDOR|PARTNER)[-_: ]?[0-9]{4,10}\b/gi },
234
- { type: 'FINANCIAL', regex: /\b(?:REVENUE|EBITDA|PROFIT|MARGIN)[\s:_-]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)?[0-9,.]+[KM]?\b/gi },
235
- { type: 'SECRET', regex: /\b(?:NDA|M&A|MERGER)[-_: ]?[A-Z0-9]{4,}\b/gi }
260
+ { type: 'ID', regex: /\b(?:DEAL|KPI|METRIC)[-_: ]+[A-Z0-9_-]{4,}\b/gi },
261
+ { type: 'ID', regex: /\b(?:ENTITY|VENDOR|PARTNER)[-_: ]+[A-Z0-9_-]{4,15}\b/gi },
262
+ { type: 'FINANCIAL', regex: /\b(?:REVENUE|EBITDA|PROFIT|MARGIN)[\s:_-]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)?[0-9,.'’]+[KM]?\b/gi },
263
+ { type: 'SECRET', regex: /\b(?:NDA|M&A|MERGER)[-_#][A-Za-z0-9_-]{3,}\b/gi },
264
+ { type: 'ID', regex: /\b(?:CAP[- ]TABLE|EQUITY|OPTION|GRANT|SHAREHOLDER)[-_ ]*(?:ID|REF)?[:\s#-]*[A-Z0-9_-]{4,20}\b/gi },
265
+ { type: 'SECRET', regex: /\b(?:VDR|DATAROOM|DEALROOM)[-_ ]*(?:CODE|ID|STAMP|REF)?[:\s#-]*[A-Za-z0-9_-]{6,25}\b/gi },
266
+ { type: 'SECRET', regex: /\b(?:TERM[- ]SHEET|VALUATION|LOI)[-_ ]*(?:REF|ID|CODE)?[:\s#-]*[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
267
+ { type: 'ID', regex: /\b(?:DUNS|D-U-N-S)(?:\s+(?:Number|No\.?|#))?[:\s#-]*(\d{2}-\d{3}-\d{4}|\d{9})\b/gi },
268
+ { type: 'ID', regex: /\b\d{10}-\d{2}-\d{6}\b/g },
269
+ { type: 'ID', regex: /\b(?:CIK|Central\s+Index\s+Key)[:\s#]*(\d{10})\b/gi },
270
+ { type: 'ID', regex: /\b(?:ES|ISO|NSO|OPT|RSU|CS|PS|SAFE|CN)[-_]\d{1,6}\b/g }
236
271
  ],
237
272
  sales: [
238
- { type: 'ID', regex: /\bOPPORTUNITY[-_: ]?[A-Z0-9]{5,}\b/gi },
273
+ { type: 'ID', regex: /\bOPPORTUNITY[-_: ]*[A-Z0-9_-]{4,}\b/gi },
274
+ { type: 'ID', regex: /\b(?:DOCUSIGN|CONTRACT)[-_: ]?[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}\b/gi },
239
275
  { type: 'ID', regex: /\b(?:DOCUSIGN|CONTRACT)[-_: ]?[0-9A-F]{8,32}\b/gi },
240
- { type: 'FINANCIAL', regex: /\b(?:ARR|MRR|QUOTA)[\s:]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)?[0-9,.]+[KM]?\b/gi },
241
- { type: 'ID', regex: /\b(?:SFDC|HUBSPOT)[-_: ]?[0-9A-Z]{15,18}\b/gi }
276
+ { type: 'FINANCIAL', regex: /\b(?:ARR|MRR|QUOTA)[\s:]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)?[0-9,.'’]+[KM]?\b/gi },
277
+ { type: 'ID', regex: /\b(?:SFDC|HUBSPOT)[-_: ]?[0-9A-Z]{15,18}\b/gi },
278
+ { type: 'ID', regex: /\b(?:GONG|CHORUS|SALESLOFT|CALL|RECORDING)[-_ ]*(?:CALL|ID|SESSION)?[:\s#-]*[A-Za-z0-9_-]{8,25}\b/gi },
279
+ { type: 'ID', regex: /\b(?:CADENCE|SEQUENCE|CAMPAIGN)[-_ ]*(?:ID|STEP)?[:\s#-]*[A-Za-z0-9_-]{5,20}\b/gi },
280
+ { type: 'ID', regex: /\b(?:ORDER[- ]FORM|MSA|SOW|QUOTE)[-_: ]*(?:REF|ID|#)?[:\s#-]*[A-Z0-9_-]{4,20}\b/gi }
242
281
  ],
243
282
  support: [
244
- { type: 'ID', regex: /\bTICKET[-_:# ]?[A-Z0-9]{5,10}\b/gi },
283
+ { type: 'ID', regex: /\bTICKET[-_:# ]*[-A-Z0-9_]*\d[-A-Z0-9_]*\b/gi },
245
284
  { type: 'ID', regex: /\b(?:ZENDESK|INTERCOM|JIRA)[-_:# ]?[0-9]{4,10}\b/gi },
246
- { type: 'ID', regex: /\b(?:REFUND|RETURN|RMA)[-_:# ]?[A-Z0-9]{6,12}\b/gi },
247
- { type: 'ID', regex: /\b(?:LOYALTY|REWARDS)[-_:# ]?\d{8,12}\b/gi }
285
+ { type: 'ID', regex: /\b(?:REFUND|RETURN|RMA)[-_:# ]*(?:ID|REF|#|NO)?[:\s#-]*[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
286
+ { type: 'ID', regex: /\b(?:LOYALTY|REWARDS)[-_:# ]?\d{8,12}\b/gi },
287
+ { type: 'ID', regex: /\b(?:INC|CHG|RITM|PRB|REQ|SCTASK|CS|TASK)\d{7,10}\b/gi },
288
+ { type: 'ID', regex: /\b(?:FRESHDESK|HELPSCOUT|CONVERSATION)[-_:# ]*(?:ID|REF)?[:\s#-]*\d{5,12}\b/gi },
289
+ { type: 'ID', regex: /\b(?:CSAT|NPS|SURVEY)[-_ ]*(?:TOKEN|SESSION|ID)?[:\s#-]*[A-Za-z0-9_-]{8,32}\b/gi }
248
290
  ],
249
291
  realestate: [
250
292
  { type: 'ID', regex: /\b(?:MLS|LIS)[- ]?\d{6,10}\b/gi },
251
293
  { type: 'ID', regex: /\bPARCEL[- ]?\d{5,15}\b/gi },
294
+ { type: 'ID', regex: /\b(?:APN|Assessor(?:'s)?\s*Parcel(?:\s*Number)?|Parcel\s*(?:ID|Number|No\.?|#))[:\s#-]*(\d{2,5}[-\s]\d{2,5}[-\s]\d{2,5}(?:[-\s]\d{1,4})?|\d{6,15})\b/gi },
252
295
  { type: 'ID', regex: /\bTENANT[-_]ID[-_][0-9]{4,}\b/gi },
253
- { type: 'FINANCIAL', regex: /(?<=\b(?:RENT|LEASE|ESCROW)[\s:]+)(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[0-9,]{3,}(?:\.\d{2})?\b/gi },
254
- { type: 'SECRET', regex: /\b(?:GATE|DOOR|LOBBY)[-_ ](?:CODE|PIN)[\s:]*\d{4,6}\b/gi }
296
+ { type: 'FINANCIAL', regex: /(?<=\b(?:RENT|LEASE|ESCROW)[\s:]+)(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[0-9,.'’]{3,}\b/gi },
297
+ { type: 'SECRET', regex: /\b(?:GATE|DOOR|LOBBY)[-_ ](?:CODE|PIN)[\s:]*\d{4,6}\b/gi },
298
+ { type: 'ID', regex: /\b(?:Escrow\s*(?:Number|No\.?|#|Account|File|Order)|Escrow)[:\s#]*([A-Za-z0-9-]{5,18})\b/gi },
299
+ { type: 'ID', regex: /\b(?:Title\s*Policy|Title\s*Order|Title\s*Commitment)\s*(?:#|ID|No\.?)?[:\s#]*([A-Z0-9-]{6,20})\b/gi },
300
+ { type: 'ID', regex: /\b(?:FHA\s*(?:Case\s*(?:No\.?|Number|#)?)?)[:\s#]*(\d{3}-\d{7})\b/gi }
255
301
  ],
256
302
  compliance: [
257
- { type: 'SECRET', regex: /\b(?:GDPR|HIPAA|CCPA|SOC2|ISO27001)[-_: ]?AUDIT[-_: ]?\d{4}\b/gi },
258
- { type: 'SECRET', regex: /\b(?:DPA|POLICY)[-_: ]?[A-Z0-9]{5,15}\b/gi },
259
- { type: 'ID', regex: /\b(?:SAR|DSAR)(?:[-_\/: ]+[A-Z0-9/_-]+|[0-9][A-Z0-9/_-]*)\b/gi }
303
+ { type: 'SECRET', regex: /\b(?:GDPR|HIPAA|CCPA|SOC2|ISO27001|NIST|SOX)[-_: ]?(?:AUDIT|COMPLIANCE)[-_: ]?(?:Q[1-4][-_ ]?)?\d{4}\b/gi },
304
+ { type: 'SECRET', regex: /\b(?:DPA|POLICY)[-_ ]*(?:ID|NO|#|CODE|REF)?[:\s_-]*[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
305
+ { type: 'ID', regex: /\b(?:SAR|DSAR)(?:[-_\/: ]+[A-Z0-9/_-]+|[0-9][A-Z0-9/_-]*)\b/gi },
306
+ { type: 'ID', regex: /\b(?:ATU\d{8}|BE\d{10}|BG\d{9,10}|CY\d{8}[A-Z]|CZ\d{8,10}|DE\d{9}|DK\d{8}|EE\d{9}|EL\d{9}|ES[A-Z0-9]\d{7}[A-Z0-9]|FI\d{8}|FR[A-Z0-9]{2}\d{9}|HR\d{11}|HU\d{8}|IE\d{7}[A-W][A-I]?|IT\d{11}|LT\d{9,12}|LU\d{8}|LV\d{11}|MT\d{8}|NL\d{9}B\d{2}|PL\d{10}|PT\d{9}|RO\d{2,10}|SE\d{12}|SI\d{8}|SK\d{10}|GB\d{9}|CHE-\d{3}\.\d{3}\.\d{3}\s?TVA)\b/g },
307
+ { type: 'ID', regex: /\b(?:SCC|STANDARD[- ]CONTRACTUAL[- ]CLAUSES?)[-_: ]*(?:2021\/914|2021[-_]EU|[A-Z0-9_-]{4,20})\b/gi },
308
+ { type: 'ID', regex: /\bBCR[-_ ]*(?:APPROVAL|CODE|ID|REF)?[-_: ]*[A-Z0-9\/-]{4,20}\b/gi },
309
+ { type: 'ID', regex: /\b(?:DPO|DATA[- ]PROTECTION[- ]OFFICER)[-_: ]*(?:REG|ID|NO|REF|FILING)?[:\s#-]*[A-Z0-9_-]{4,20}\b/gi },
310
+ { type: 'ID', regex: /\b(?:ICO\s+(?:Reg(?:istration)?|Ref|No\.?|#)?)[:\s#-]*([Zz][A-Za-z0-9]?\d{6,7})\b/gi },
311
+ { type: 'ID', regex: /\bFR\d{8,10}\b/g },
312
+ { type: 'ID', regex: /\bEDPBI:[A-Z]{2}:OSS:[A-Z]:\d{4}:\d{3,6}\b/g },
313
+ { type: 'ID', regex: /\b(?:AC|AT|AU|CA|CM|CP|IA|IR|MA|MP|PE|PL|PS|RA|SA|SC|SI|SR)-\d{1,2}(?:\(\d{1,2}\))?\b/g }
260
314
  ],
261
315
  ccpa: [
262
- { type: 'ID', regex: /\b(?:DL|DRIVER['’]?S?\s+LICENSE)[:\s#-]*[A-Z0-9]{6,12}\b/gi },
263
- { type: 'LOCATION', regex: /\b-?\d{1,3}\.\d{4,6}[° ]?[NSns],\s*-?\d{1,3}\.\d{4,6}[° ]?[EWew]\b/g },
316
+ { type: 'ID', regex: /\b(?:DL|DRIVER['’]?S?\s+LICENSE(?:\s+DL)?)[:\s#-]*[-A-Z0-9]{6,15}\b/gi },
317
+ { type: 'LOCATION', regex: /\b-?(?:[0-8]?\d(?:\.\d{3,8})?|90(?:\.0{3,8})?)\s*[°\s]*,\s*-?(?:1[0-7]\d(?:\.\d{3,8})?|180(?:\.0{3,8})?|[0-9]?\d(?:\.\d{3,8})?)\s*\b/g },
264
318
  { type: 'ID', regex: /\b(?:CCPA|CPRA)[-_: ]?OPT[-_ ]OUT\b/gi },
265
- { type: 'ID', regex: /\bACCOUNT[ -]?(?:ID|NUM|NUMBER)[:\s]+[A-Z0-9]{6,20}\b/gi }
319
+ { type: 'ID', regex: /\bACCOUNT[ -]?(?:ID|NUM|NUMBER)[:\s]+[-A-Z0-9]{6,25}\b/gi },
320
+ { type: 'ID', regex: /\b(?:CCPA|CPRA)\s*(?:Request|Inquiry|Ticket|SAR)\s*(?:ID|#|Ref)?[:\s#-]*([A-Za-z0-9_-]{6,36})\b/gi },
321
+ { type: 'SECRET', regex: /\b(?:FACE|VOICE|BIO|FP|IRIS)[-_ ]?(?:TEMPLATE|PRINT|VECTOR|HASH|ID)?[:\s#-]*([a-fA-F0-9]{32,64})\b/gi }
266
322
  ],
267
323
  engineering: [
324
+ ...DEVOPS_SECRETS,
268
325
  { type: 'SECRET', regex: /(?<=\b(?:DB|POSTGRES|REDIS|MYSQL|AWS|SECRET|PASSWORD|TOKEN|API|KEY)[A-Z0-9_]*\s*[:=]\s*["']?)[A-Za-z0-9_-]{10,}/gi },
269
326
  { type: 'ID', regex: /\b[a-z0-9._-]+\/[a-z0-9._-]+:[a-z0-9._-]+\b/g },
270
327
  { type: 'ID', regex: /\b[a-fA-F0-9]{40}\b/g },
271
- { type: 'ID', regex: /\b[a-z0-9](?:[-a-z0-9]*[a-z0-9])?\.svc\.cluster\.local\b/g }
328
+ { type: 'ID', regex: /\b[a-z0-9](?:[-a-z0-9]*[a-z0-9])?\.svc\.cluster\.local\b/g },
329
+ { type: 'ID', regex: /\barn:(?:aws|aws-cn|aws-us-gov):[a-z0-9-]+:[a-z0-9-]*:(?:\d{12})?:[a-zA-Z0-9-_\/.:*]+\b/g },
330
+ { type: 'ID', regex: /\b(?:[a-z0-9]+(?:[._-][a-z0-9]+)*\/)*[a-z0-9._-]+@sha256:[a-f0-9]{64}\b/g }
272
331
  ],
273
332
  agents: [
274
- { type: 'ID', regex: /\b(?:AGENT|VECTOR|EMBEDDING)[-_: ]?(?:ID[-_: ]?)?[A-Z0-9]{8,}\b/gi },
275
- { type: 'ID', regex: /\bTASK[-_: ]?[A-Z0-9]{5,15}\b/gi },
276
- { type: 'SECRET', regex: /\b(?:SYS_PROMPT|SYSTEM_PROMPT|OPENAI_API_KEY)[-_: ]?[A-Za-z0-9_-]{10,}\b/gi }
333
+ { type: 'ID', regex: /\b(?:AGENT|VECTOR|EMBEDDING)[-_: ]*(?:ID[-_: ]*)?[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
334
+ { type: 'ID', regex: /\bTASK[-_: ]?[A-Z0-9_-]{4,15}\b/gi },
335
+ { type: 'SECRET', regex: /\b(?:SYS[-_]PROMPT|SYSTEM[-_]PROMPT|OPENAI[-_]API[-_]KEY)[-_: ]?[A-Za-z0-9_-]{10,}\b/gi },
336
+ { type: 'ID', regex: /\basst_[a-zA-Z0-9]{20,32}\b/g },
337
+ { type: 'ID', regex: /\b(?:thread|run)_[a-zA-Z0-9]{20,32}\b/g },
338
+ { type: 'ID', regex: /\b(?:PINECONE|WEAVIATE|QDRANT|MILVUS|CHROMA)[-_ ]*(?:INDEX|COLLECTION|NAMESPACE)?[:\s#-]*[a-zA-Z0-9_-]{4,30}\b/gi },
339
+ { type: 'ID', regex: /\b(?:vs|vsfb)_[a-zA-Z0-9]{24}\b/g },
340
+ { type: 'ID', regex: /\bfile-[a-zA-Z0-9]{24}\b/g },
341
+ { type: 'ID', regex: /\bftjob-[a-zA-Z0-9]{24}\b/g },
342
+ { type: 'ID', regex: /\bmsgbatch_[a-zA-Z0-9]{24,32}\b/g },
343
+ { type: 'SECRET', regex: /\bhf_[a-zA-Z0-9]{34,40}\b/g }
277
344
  ],
278
345
  academic: [
279
- { type: 'ID', regex: /\b(?:STUDENT|ALUMNI)[-_:# ]?[0-9]{5,10}\b/gi },
280
- { type: 'ID', regex: /\bCOURSE[-_:# ]?[A-Z]{3,4}[ ]?[0-9]{3,4}\b/gi },
346
+ { type: 'ID', regex: /\b(?:STUDENT|ALUMNI)[-_:# ]*[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
347
+ { type: 'ID', regex: /\bCOURSE[-_:# ]?[A-Z]{2,4}[ ]?[0-9]{3,4}\b/gi },
281
348
  { type: 'ID', regex: /\b(?:FERPA|IRB)[-_:# ]*[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
282
- { type: 'ID', regex: /\bGRADE[S]?[\s:][A-DF][+-]?\b/gi }
349
+ { type: 'ID', regex: /\bGRADE[S]?[:\s]+[A-DF][+-]?\b/gi },
350
+ { type: 'ID', regex: /\b(?:[1-9]\s?)?[A-Z][0-9]{2}[A-Z]{2}[0-9]{6}(?:-[0-9]{2})?\b/g },
351
+ { type: 'ID', regex: /\bN\d{10}\b/g },
352
+ { type: 'ID', regex: /\b(?:TRANSCRIPT|REGISTRAR|DIPLOMA)[-_ ]*(?:ID|REF|NO)?[:\s#-]*[A-Za-z0-9_-]*\d[A-Za-z0-9_-]*\b/gi },
353
+ { type: 'ID', regex: /\b000[0-9]-[0-9]{4}-[0-9]{4}-[0-9]{3}[0-9X]\b/g },
354
+ { type: 'ID', regex: /\b10\.\d{4,9}\/[-._;()/:A-Za-z0-9]+\b/g },
355
+ { type: 'ID', regex: /\b(?:arXiv:)?(\d{4}\.\d{4,5}(?:v\d+)?)\b/g },
356
+ { type: 'ID', regex: /\bPMID[:\s#]*(\d{4,8})\b/gi },
357
+ { type: 'ID', regex: /\bPMC\d{7,8}\b/g }
283
358
  ],
284
359
  creative: [
285
- { type: 'SECRET', regex: /\b(?:PROJECT|DRAFT|ASSET|SCRIPT|IP)[-_: ]?[0-9]{4,10}\b/gi },
360
+ { type: 'SECRET', regex: /\b(?:PROJECT|DRAFT|ASSET|SCRIPT|IP)[-_: ]+[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi },
286
361
  { type: 'SECRET', regex: /\b(?:SPOILER|UNRELEASED|EMBARGOED)\b/gi },
287
- { type: 'NAME', regex: /\b(?:GHOSTWRITER|SOURCE)[:\s][A-Z][a-z]+ [A-Z][a-z]+\b/g }
362
+ { type: 'NAME', regex: /\b(?:GHOSTWRITER|SOURCE)[:\s][A-Z][a-z]+ [A-Z][a-z]+\b/g },
363
+ { type: 'ID', regex: /\b(?:WGA|WGAW|WGAE)[-_: ]*(?:REGISTRATION|REG|#)?[:\s#-]*\d{6,10}\b/gi },
364
+ { type: 'ID', regex: /\bISAN\s?[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]\b/gi },
365
+ { type: 'SECRET', regex: /\b(?:TALENT|MODEL|ACTOR|CAST)[-_ ]RELEASE[-_ ]*(?:ID|NO|REF)?[:\s#-]*[A-Za-z0-9_-]*\d[A-Za-z0-9_-]*\b/gi },
366
+ { type: 'ID', regex: /\b(?:ISRC[:\s#]*)?([A-Z]{2}-?[A-Z0-9]{3}-?[0-9]{2}-?[0-9]{5})\b/g },
367
+ { type: 'ID', regex: /\b(?:ISBN(?:-1[03])?[:\s#]*)?(?:97[89][-\s]?)?\d{1,5}[-\s]?\d{1,7}[-\s]?\d{1,6}[-\s]?[0-9X]\b/g },
368
+ { type: 'ID', regex: /\b10\.\d{4,9}\/[-._;()/:A-Za-z0-9]+\b/g },
369
+ { type: 'ID', regex: /\b10\.5240\/(?:[0-9A-Fa-f]{4}-){5}[0-9A-Za-z]\b/g },
370
+ { type: 'ID', regex: /\b(?:SAG(?:-AFTRA)?|AFTRA)\s*(?:ID|#|Member(?:ship)?|No\.?)[:\s#-]*(\d{6,8})\b/gi },
371
+ { type: 'ID', regex: /\b(?:IPI|CAE|ASCAP|BMI|SESAC)\s*(?:Party|Writer|Publisher|Account|ID|#|No\.?)[:\s#-]*(\d{6,11})\b/gi }
288
372
  ],
289
373
  tech: [
290
- { type: 'ID', regex: /\b(?:INSTANCE|NODE|CLUSTER)[-_]ID[-_][a-z0-9-]{10,}\b/gi },
291
- { type: 'ID', regex: /\bENV[-_: ]?(?:PROD|STAGING|DEV|TEST|QA)\b/gi },
292
- { type: 'SECRET', regex: /\b(?:CONFIG|KUBECONFIG|TFSTATE)[-_: ]?[A-Z0-9]{6,15}\b/gi }
374
+ ...DEVOPS_SECRETS,
375
+ { type: 'ID', regex: /\b(?:INSTANCE|NODE|CLUSTER)[-_]ID[-_][a-z0-9-]{5,30}\b/gi },
376
+ { type: 'ID', regex: /\bENV[-_: ]*(?:PROD|STAGING|DEV|TEST|QA)\b/gi },
377
+ { type: 'SECRET', regex: /\b(?:CONFIG|KUBECONFIG|TFSTATE)[-_: ]?[A-Z0-9_-]{4,20}\b/gi },
378
+ { type: 'ID', regex: /\b(?:GCP[- ]PROJECT|PROJECT[- ]ID)[:\s#-]*[a-z][a-z0-9-]{4,28}[a-z0-9]\b/gi },
379
+ { type: 'ID', regex: /\b(?:AZURE[- ](?:SUBSCRIPTION|TENANT)|AZ[- ]SUB)[:\s#-]*[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/gi },
380
+ { type: 'ID', regex: /\b(?:i|sg|vpc|subnet|ami|snap|vol|eni|rtb|nat|igw|vgw|tgw|pcx|eipalloc|acl)-[a-f0-9]{8,17}\b/g },
381
+ { type: 'ID', regex: /\b\/subscriptions\/[0-9a-fA-F-]{36}\/resourceGroups\/[a-zA-Z0-9._-]+\/providers\/[a-zA-Z0-9._-]+\/[a-zA-Z0-9._\/-]+\b/gi }
293
382
  ],
294
383
  personal: [
295
384
  { type: 'DATE', regex: /\b(?:DOB|BIRTHDAY|Date of Birth)[\s:]+([0-9./-]{6,10})\b/gi },
296
385
  { type: 'SECRET', regex: /\b(?:PASSWORD|PWD|SECRET|PIN)[\s:]*[\S]{4,20}\b/gi },
297
- { type: 'PHONE', regex: /\b(?:WIFE|HUSBAND|PARTNER|MOM|DAD)[\s:]+(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]\d{3}[-.\s]\d{4}\b/gi }
386
+ { type: 'PHONE', regex: /\b(?:WIFE|HUSBAND|PARTNER|MOM|DAD)[\s:]+(?:\+?\d{1,3}[\s.-]*)?(?:\(?\d{2,4}\)?[\s.-]*)?[\d\s.-]{7,15}\b/gi },
387
+ { type: 'FINANCIAL', regex: /\b(?:CHECKING|SAVINGS|DEPOSIT)\s*(?:ACCOUNT|ACCT)?[:\s#-]*\d{6,17}\b/gi },
388
+ { type: 'PHONE', regex: /\b(?:SON|DAUGHTER|BROTHER|SISTER|MOTHER|FATHER|CHILD|PARENT)[\s:]+(?:\+?\d{1,3}[\s.-]*)?(?:\(?\d{2,4}\)?[\s.-]*)?[\d\s.-]{7,15}\b/gi },
389
+ { type: 'SECRET', regex: /\b(?:MASTER|DEVICE|BACKUP|SAFE)\s*(?:PIN|PASSCODE|CODE)[\s:]*\d{4,8}\b/gi },
390
+ { type: 'ID', regex: /\b(?:Passport)(?:\s+(?:Number|No\.?|#))?[:\s#]*([A-Z0-9]{8,10})\b/gi },
391
+ { type: 'ID', regex: /\b(?:SkyMiles|AAdvantage|MileagePlus|Rapid\s+Rewards|Frequent\s+Flyer|Marriott|Bonvoy|Hilton\s+Honors|Hyatt|Rewards?|Loyalty)\s*(?:#|No\.?|Number|Account)?[:\s#]*([A-Z0-9-]{7,12})\b/gi }
298
392
  ],
299
393
  wealthmgmt: [
300
394
  { type: 'LEGAL', regex: /\b(?:THE\s+)?[A-Z][A-Z\s.'-]{4,}\s+(?:(?:REVOCABLE|IRREVOCABLE|LIVING|FAMILY|TESTAMENTARY|CHARITABLE|GENERATION-SKIPPING)\s+)*TRUST\b/g },
301
395
  // Mixed-Caps name: All-Caps first name (3+ chars) + optional initials + Mixed-Case last name
302
396
  // Handles PDF-rendered trust names where OCR/extraction produces e.g. "KKKKK I. Mmmmmmm"
303
397
  { type: 'NAME', regex: /(?<=^|[^\p{L}\p{N}_])\p{Lu}{3,}(?:[\p{Lu}'-]*\p{Lu})?(?:[ \t\xA0]+\p{Lu}\.)*[ \t\xA0]+\p{Lu}\p{Ll}[\p{Ll}'-]*(?:\p{Lu}[\p{Ll}'-]*)?\p{L}(?:'s)?(?=[^\p{L}\p{N}_]|$)/gu },
398
+ { type: 'ID', regex: /\b(?:TRUST|ANNUITY|BENEFICIARY)[-_][A-Z0-9_-]{4,20}\b/gi },
399
+ { type: 'ID', regex: /\b(?:LEI|LEGAL[- ]ENTITY[- ]IDENTIFIER)[:\s#-]*[0-9A-Z]{20}\b/gi },
304
400
  { type: 'FINANCIAL', regex: /\b(?:ABA|Routing(?:\s+No)?|RTN)[:\s#]*\d{9}\b/gi },
401
+ { type: 'FINANCIAL', regex: /\bPORTFOLIO[-_][A-Z0-9_-]{5,}\b/gi },
402
+ { type: 'FINANCIAL', regex: /\b(?:Account|Acct\.?|Brokerage|Custodial)\s*(?:Account|Acct)?\s*(?:Number|Num|No\.?|#)?[:\s#]*\d{6,16}\b/gi },
305
403
  { type: 'FINANCIAL', regex: /\b(?:Account|Acct\.?)[:\s#]*\d{4}[-\s]?\d{4}[-\s]?\d{2,6}\b/gi },
306
404
  { type: 'FINANCIAL', regex: /\b(?:Policy|Contract)\s*(?:No\.?|Number|#)[:\s]+[A-Z0-9][A-Z0-9\-]{3,14}\b/gi },
307
405
  { type: 'ID', regex: /\bCRD\s*#?\s*\d{4,8}\b/gi },
308
- { type: 'FINANCIAL', regex: /\b(?:Annual\s+(?:Distribution|Withdrawal)|RMD|Required\s+Minimum\s+Distribution)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,]+(?:[.][\d]{2})?\b/gi },
309
- { type: 'FINANCIAL', regex: /\b(?:Portfolio|Market\s+Value|Net\s+Worth|AUM|Total\s+Assets)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.]+[KMB]?\b/gi },
310
- { type: 'FINANCIAL', regex: /\b(?:Roth\s+)?(?:IRA|401k|401\(k\)|403b|403\(b\)|SEP|SIMPLE)\s*(?:Account|Acct|Plan)?\s*(?:No|Number|#)?[:\s#]*[A-Z0-9]{4,15}\b/gi }
406
+ { type: 'FINANCIAL', regex: /\b(?:Annual\s+(?:Distribution|Withdrawal)|RMD|Required\s+Minimum\s+Distribution)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.'’]+\b/gi },
407
+ { type: 'FINANCIAL', regex: /\b(?:Portfolio|Market\s+Value|Net\s+Worth|AUM|Total\s+Assets)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.'’]+[KMB]?\b/gi },
408
+ { type: 'FINANCIAL', regex: /\b(?:Roth\s+)?(?:IRA|401k|401\(k\)|403b|403\(b\)|SEP|SIMPLE)\s*(?:Account|Acct|Plan)?\s*(?:No|Number|#)?[:\s#]*[A-Z0-9]{4,15}\b/gi },
409
+ { type: 'ID', regex: /\bCUSIP[:\s#]*([0-9A-Z]{9})\b/gi },
410
+ { type: 'ID', regex: /\bISIN[:\s#]*([A-Z]{2}[0-9A-Z]{9}[0-9])\b/gi },
411
+ { type: 'ID', regex: /\b(?:Form\s+ADV|SEC)\s*(?:File|No\.?|Number|#)?[:\s#]*(?:801|802)-\d{5,8}\b/gi },
412
+ { type: 'ID', regex: /\bSeries\s+(?:7|63|65|66)\s*(?:License|#|No\.?|Number)?[:\s#]*\d{4,8}\b/gi }
311
413
  ],
312
414
  insurance: [
313
- { type: 'ID', regex: /\b(?:Claim|CLM)[:\s#-]*[A-Z0-9]{6,15}\b/gi },
314
- { type: 'ID', regex: /\b(?:Policy|POL)[:\s#-]*[A-Z]{0,4}[-]?\d{6,12}\b/gi },
315
- { type: 'FINANCIAL', regex: /\b(?:Loss|Claim\s+Amount|Settlement|Reserve|Indemnity)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,]+(?:[.]\d{2})?\b/gi },
316
- { type: 'ID', regex: /\b(?:Adjuster\s+(?:ID|No)|Claim\s+Rep(?:\.|resentative)?)[:\s#]*[A-Z0-9]{4,12}\b/gi },
317
- { type: 'ID', regex: /\bNAIC[:\s#]*\d{5}\b/gi },
318
- { type: 'FINANCIAL', regex: /\b(?:Deductible|Premium|Coverage\s+Amount)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,]+(?:[.]\d{2})?\b/gi },
415
+ { type: 'ID', regex: /\b(?:Claim|CLM)[-_: #]*(?:ID|NO|#|NUM|NUMBER|REF)?[:\s#-]*[-A-Z0-9]*\d[-A-Z0-9]*\b/gi },
416
+ { type: 'ID', regex: /\b(?:Policy|POL)[-_: #]*(?:ID|NO|#|NUM|NUMBER)?[:\s#-]*[-A-Z0-9]*\d[-A-Z0-9]*\b/gi },
417
+ { type: 'FINANCIAL', regex: /\b(?:Loss|Claim\s+Amount|Claim\s+Settlement|Settlement|Reserve|Indemnity)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.'’]+\b/gi },
418
+ { type: 'ID', regex: /\b(?:(?:Assigned\s+)?Adjuster\s+(?:ID|No)|Claim\s+Rep(?:\.|resentative)?)[:\s#]*[-A-Z0-9]{4,15}\b/gi },
419
+ { type: 'ID', regex: /\bNAIC(?:\s+(?:Company\s+)?(?:Code|CoCode|No\.?|Number|#))?[:\s#]*(\d{5})\b/gi },
420
+ { type: 'FINANCIAL', regex: /\b(?:Deductible|Premium|Coverage\s+Amount)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.'’\u2018\u2019]+\b/gi },
319
421
  { type: 'ID', regex: /\b[A-HJ-NPR-Z0-9]{17}\b/g },
320
422
  { type: 'ID', regex: /\b(?:Insured|Named\s+Insured)[:\s]+[A-Z][a-z]+(?:\s+[A-Z][a-z]+)+/g },
321
- { type: 'ID', regex: /\b(?:Agent|Producer)\s*(?:Code|No|ID)[:\s#]*[A-Z0-9]{4,12}\b/gi }
423
+ { type: 'ID', regex: /\b(?:Agent|Producer)\s*(?:Code|No|ID)[:\s#]*[-A-Z0-9]{4,15}\b/gi },
424
+ { type: 'ID', regex: /\b(?:Binder|Certificate(?:\s+of\s+Insurance)?|COI)\s*(?:ID|No\.?|Number|#)?[:\s#-]*([A-Za-z0-9\/-]{4,30})\b/gi },
425
+ { type: 'ID', regex: /\b(?:FCA|FRN|Firm\s*Reference\s*(?:Number|No\.?|#))[:\s#]*(\d{6,7})\b/gi },
426
+ { type: 'ID', regex: /\b(?:Lloyd'?s\s+)?Syndicate\s*(?:No\.?|Number|#)?[:\s#]*(\d{1,4})\b/gi },
427
+ { type: 'ID', regex: /\b(?:AM\s*Best|AMB)\s*(?:#|No\.?|Number|ID)?[:\s#]*(\d{6})\b/gi }
322
428
  ],
323
429
  accounting: [
324
430
  { type: 'ID', regex: /\b(?:EIN|FEIN|Tax\s+ID)[:\s#]*\d{2}-\d{7}\b/gi },
325
- { type: 'FINANCIAL', regex: /\b(?:AGI|Adjusted\s+Gross\s+Income|Taxable\s+Income|Total\s+Income)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,]+(?:[.]\d{2})?\b/gi },
326
- { type: 'FINANCIAL', regex: /\bBox\s+\d{1,2}[a-z]?[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,]+(?:[.]\d{2})?\b/gi },
431
+ { type: 'FINANCIAL', regex: /\b(?:AGI|Adjusted\s+Gross\s+Income|Taxable\s+Income|Total\s+Income)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.'’]+\b/gi },
432
+ { type: 'FINANCIAL', regex: /\b(?:Form\s+|Withheld\s+)?Box\s+\d{1,2}[a-z]?(?:\s*:\s*[A-Z])?\s*[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.'’\u2018\u2019]+\b/gi },
327
433
  { type: 'ID', regex: /\b(?:Form|Schedule)\s+(?:1040|1040-SR|W-2|W-4|1099-[A-Z]{1,4}|K-1|941|990|4562)\b/gi },
328
- { type: 'FINANCIAL', regex: /\b(?:Federal|State)\s+(?:Tax\s+)?(?:Refund|Amount\s+Owed|Balance\s+Due)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,]+(?:[.]\d{2})?\b/gi },
434
+ { type: 'FINANCIAL', regex: /\b(?:Federal|State|Assessed)?\s*(?:Tax\s+Due|Balance\s+Due|Overpayment|Refund)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.'’\u2018\u2019]+\b/gi },
329
435
  { type: 'ID', regex: /\b(?:State\s+Tax\s+ID|SUI|UI\s+Account\s+No)[:\s#]*[A-Z]{0,3}[-]?\d{4,15}\b/gi },
330
- { type: 'FINANCIAL', regex: /\b(?:Net\s+Pay|Gross\s+Pay|Taxable\s+Wages)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,]+(?:[.]\d{2})?\b/gi },
331
- { type: 'ID', regex: /\b(?:CAF|Practitioner\s+(?:PIN|ID)|PTIN)[:\s#]*[A-Z]?\d{6,9}\b/gi }
436
+ { type: 'FINANCIAL', regex: /\b(?:Gross|Net|Medicare|Social\s+Security)\s+(?:Pay|Wages|Tips|Withholding)[:\s]+(?:[$€£¥₪₽₹]|(?:USD|EUR|GBP|CHF|ILS|RUB)\s?)[\d,.'’\u2018\u2019]+\b/gi },
437
+ { type: 'ID', regex: /\b(?:CAF(?:\s+ID)?|(?:Practitioner|Tax\s+Preparer)\s+(?:PIN|ID)|PTIN)[:\s#]*[A-Z0-9-]{6,12}\b/gi },
438
+ { type: 'ID', regex: /\bEFIN[:\s#]*\d{6}\b/gi },
439
+ { type: 'ID', regex: /\bGL[-_\s]*(?:Account|Acct|Code)?[:\s#]*\d{4,10}\b/gi },
440
+ { type: 'ID', regex: /\b(?:Cost\s+Center|CC)[-_\s]*(?:ID|Code|#)?[:\s#]*[A-Z0-9_-]*\d[A-Z0-9_-]*\b/gi }
332
441
  ],
333
442
  pharma: [
334
- { type: 'ID', regex: /\b(?:Subject|Patient|Participant)\s+(?:ID|No)[:\s#]*[A-Z0-9]{3,12}\b/gi },
443
+ { type: 'ID', regex: /\b(?:Subject|Patient|Participant)\s+(?:ID|No)[:\s#]*[-A-Z0-9]{3,15}\b/gi },
335
444
  { type: 'ID', regex: /\b(?:Protocol|Study)\s*(?:No|Number|ID)[:\s#]*[A-Z0-9][-A-Z0-9]{3,15}\b/gi },
336
445
  { type: 'ID', regex: /\b(?:IND|NDA|BLA|ANDA)\s*(?:No|Number|#)?[:\s]*\d{3,6}\b/gi },
337
- { type: 'ID', regex: /\bIRB[:\s#]*[A-Z0-9]{4,12}\b/gi },
338
- { type: 'ID', regex: /\b(?:Site\s+(?:No|ID)|Investigator\s+Site)[:\s#]*\d{3,6}\b/gi },
339
- { type: 'ID', regex: /\b(?:Batch|Lot|Serial)\s*(?:No[.]?|Number|#)?[:\s#]*[A-Z0-9][A-Z0-9\-]{3,14}\b/gi },
446
+ { type: 'ID', regex: /\bIRB[:\s#]*[-A-Z0-9]{4,15}\b/gi },
447
+ { type: 'ID', regex: /\b(?:(?:Clinical\s+)?Site\s+(?:No|ID)|Investigator\s+Site)[:\s#]*[-A-Z0-9]{3,10}\b/gi },
448
+ { type: 'ID', regex: /\b(?:(?:Manufacturing\s+)?(?:Batch|Lot)|Serial)\s*(?:No[.]?|Number|#)?[:\s#]*[A-Z0-9][A-Z0-9\-]{3,14}\b/gi },
340
449
  { type: 'PHI', regex: /\b(?:Dose|Dosage)[:\s]+\d+(?:\.\d+)?\s*(?:mg|mcg|mL|IU|units?)\b/gi },
341
- { type: 'ID', regex: /\b(?:CRF|eCRF|Case\s+Report\s+Form)\s*(?:No|Page|ID)?[:\s#]*[A-Z0-9]{2,10}\b/gi }
450
+ { type: 'ID', regex: /\b(?:eCRF|CRF|(?:Electronic\s+)?Case\s+Report\s+Form)\s*(?:No|Page|ID)?[:\s#]*[A-Z0-9-]{2,15}\b/gi },
451
+ { type: 'ID', regex: /\bNCT\d{8}\b/gi },
452
+ { type: 'ID', regex: /\b(?:EudraCT|EU\s*CT)?[:\s#]*(20\d{2}-\d{6}-\d{2})\b/gi },
453
+ { type: 'ID', regex: /\b[Kk]\d{6}\b/g },
454
+ { type: 'ID', regex: /\b[Pp]\d{6}(?:\/S\d{3})?\b/g },
455
+ { type: 'ID', regex: /\b(?:USUBJID|SUBJID|STUDYID|SITEID|INVID)[:\s=]+["']?([A-Za-z0-9_-]{3,35})["']?\b/gi },
456
+ { type: 'ID', regex: /\b(?:Randomization|Rand|RND)\s*(?:ID|Code|No\.?|Number|#)?[:\s#-]*([A-Za-z0-9-]{3,15})\b/gi },
457
+ { type: 'ID', regex: /\b(?:Kit|Medication\s*Kit|Bottle|Dispensing)\s*(?:ID|No\.?|Number|#)?[:\s#-]*([A-Za-z0-9-]{3,15})\b/gi },
458
+ { type: 'ID', regex: /\b(?:SAE|AER|ICSR|CIOMS|Safety\s*Report)\s*(?:ID|No\.?|Number|#|Ref)?[:\s#-]*([A-Za-z0-9-]{4,25})\b/gi }
342
459
  ],
343
460
  underwriting: [
344
461
  // Employer Corporate / Business Names
345
- { type: 'NAME', isContextName: true, regex: /\b(?:[A-Z][A-Za-z0-9&.,'-]*[ \t\xA0]+){1,5}(?:Inc\.?|LLC|Corp\.?|Corporation|Ltd\.?|Limited|Co\.?|Company|Group|Holdings|Solutions|Services|Technologies|Logistics|Industries|Capital|Bank|Partners|LLP|PLLC)(?:\s+(?:LLC|Inc\.?|Corp\.?|Ltd\.?|USA|Group))?\b/g },
462
+ { type: 'NAME', isContextName: true, isCorporateName: true, regex: /\b(?:[A-Z][A-Za-z0-9&.,'-]*[ \t\xA0]+){1,5}(?:Inc\.?|LLC|Corp\.?|Corporation|Ltd\.?|Limited|Co\.?|Company|Group|Holdings|Solutions|Services|Technologies|Logistics|Industries|Capital|Bank|Partners|LLP|PLLC)(?:\s+(?:LLC|Inc\.?|Corp\.?|Ltd\.?|USA|Group))?\b/g },
346
463
  { type: 'NAME', isContextName: true, regex: /(?:Employer|Company|Organization|Business)\s*(?:Name)?[\s:#]+([A-Za-z0-9&.,\s'-]{2,40}?)(?=\r?\n|$|\s{3,}|\t|Address|EIN|FEIN|Phone|W-2|Rate|Pay|Wage)/gi },
347
464
 
348
465
  // W-2 & Tax Identifiers
349
- { type: 'ID', regex: /(?:\b(?:Box\s+d\b|d\.\s*(?:Control|#)?|d\s+Control)\s*(?:number|no\.?|#|num)?[:\s#]*|\bControl\s*(?:number|no\.?|#|num)[:\s#]*|\bControl[:#]\s*)([A-Za-z0-9-]{3,30})/gi },
466
+ { type: 'ID', regex: /(?:\b(?:Box\s+d\b|d\.\s*(?:Control|#)?|d\s+Control)\s*(?:Control\s+)?(?:number|no\.?|#|num)?[:\s#]+|\bControl\s*(?:number|no\.?|#|num)?[:\s#]+|\bControl[:#]\s*)([A-Za-z0-9-]{3,30})/gi },
350
467
  { type: 'ID', regex: /\b(?:EIN|FEIN|Tax\s+ID)[:\s#]*\d{2}-\d{7}\b/gi },
351
468
  { type: 'ID', regex: /\b\d{2}-\d{7}\b/g },
352
469
  { type: 'ID', regex: /\b\d{3}-\d{2}-\d{4}\b/g },
@@ -354,7 +471,7 @@ let PROFILE_RULES = {
354
471
 
355
472
  // Employee, Loan & Payroll IDs
356
473
  { type: 'ID', regex: /\b(?:Employee|Emp|EE|Worker|Borrower|Badge|Advisor|Producer|Agent|Applicant|File)\s*(?:#|ID|No\.?|Number)[:\s#]*[A-Z0-9-]{3,20}\b/gi },
357
- { type: 'ID', regex: /\b(?:Pay\s+Group|Cost\s+Center|Dept|Department)(?:[:#][\s#]*[A-Za-z0-9_-]{2,30}|\s+[A-Za-z0-9_-]*\d[A-Za-z0-9_-]*)\b/gi },
474
+ { type: 'ID', regex: /\b(?:Pay\s+Group[:#\s]+[A-Za-z0-9_-]{2,30}|(?:Cost\s+Center|Dept|Department)[:#\s]+[A-Za-z0-9_-]*\d[A-Za-z0-9_-]*)\b/gi },
358
475
  { type: 'ID', regex: /\b(?:Loan|Application|Deal|Borrower|File)\s*(?:#|ID|No\.?|Number)[:\s#]*[A-Za-z0-9-]{4,25}\b/gi },
359
476
 
360
477
  // Direct Deposit, Bank Accounts & Routing Numbers (Masked & Unmasked)
@@ -369,7 +486,7 @@ let PROFILE_RULES = {
369
486
 
370
487
  // Addresses & Locations
371
488
  { type: 'ADDRESS', isContextAddress: true, regex: /(?:(?:Borrower(?:'s)?|Co-Borrower(?:'s)?|Employee(?:'s)?|Employer(?:'s)?|Home|Mailing|Property|Physical)\s+address|(?:(?:\bBox\s+f\b|\bf\.\s*|\bf\s+(?=Employee))\s*(?:Employee(?:'s)?\s*)?address))[\s:#]+([A-Za-z0-9#.,\s-]{4,55}?)(?=\r?\n|$|\s{3,}|\t|City|State|ZIP|SSN|EIN|Phone|Box|\d+\b)/gi },
372
- { type: 'ADDRESS', regex: /\b\d{1,6}[ \t\xA0]+(?:[A-Za-z0-9.-]+[ \t\xA0]+){1,4}(?:St|Street|Ave|Avenue|Blvd|Boulevard|Rd|Road|Ln|Lane|Dr|Drive|Way|Ct|Court|Pl|Place|Terrace|Pkwy|Parkway|Sq|Square|Hwy|Highway|Cir|Circle|Trl|Trail|Loop|Row|Pike|Box|PO Box|P\.O\.[ \t\xA0]*Box)\b(?:[ \t\xA0]*,?[ \t\xA0]*(?:Apt|Apartment|Suite|Ste|Unit|#|Fl|Floor|Bldg|Building)\.?[ \t\xA0]*[A-Za-z0-9-]+)?/gi },
489
+ { type: 'ADDRESS', regex: /\b\d{1,6}[ \t\xA0]+(?:[A-Za-z0-9.-]+[ \t\xA0]+){1,4}(?:St|Street|Ave|Avenue|Blvd|Boulevard|Rd|Road|Ln|Lane|Dr|Drive|Way|Ct|(?<!District |Supreme |Circuit |Appellate |Bankruptcy |High |Federal |Trial )Court|Pl|Place|Terrace|Pkwy|Parkway|Sq|Square|Hwy|Highway|Cir|Circle|Trl|Trail|Loop|Row|Pike|PO Box|P\.O\.[ \t\xA0]*Box)\b(?:[ \t\xA0]*,?[ \t\xA0]*(?:Apt|Apartment|Suite|Ste|Unit|#|Fl|Floor|Bldg|Building)\.?[ \t\xA0]*[A-Za-z0-9-]+)?/gi },
373
490
  { type: 'ADDRESS', regex: /\b[A-Za-z][a-zA-Z\s.-]{1,25},?\s+(?:AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY|DC|PR)\s+\d{5}(?:-\d{4})?\b/g },
374
491
  { type: 'ADDRESS', regex: /\b\d{5}-\d{4}\b/g },
375
492
  { type: 'LOCATION', regex: /\b[A-Za-z][a-zA-Z .'-]{1,25}(?:,\s*(?:AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY|DC|PR)|\s+(?:AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY|DC|PR))\b/g }
@@ -420,7 +537,7 @@ let NAME_STOP_LIST = new Set([
420
537
  'step 1', 'step 2', 'step 3', 'step 4', 'step 5',
421
538
  'page 1', 'page 2', 'page 3', 'page 4', 'page 5',
422
539
  'cs101', 'course cs101',
423
- 'docket number', 'docket numbers', 'dockets section', 'case name', 'case names', 'case number', 'case numbers', 'law firm', 'law firms', 'counsel stack', 'counselstack', 'counselstack connector', 'tier 0', 'tier 1', 'tier 2', 'tier 3', 'tier 4', 'do not', 'do not write', 'specific permission', 'write again', 'without permission', 'without specific permission', 'on screen', 'in report', 'own line', 'connector access', 'prompt instruction', 'prompt instructions', 'finding report', 'findings report', 'wage and tax statement', 'form w-2', 'wage and tax', 'tax statement', 'u.s. individual', 'income tax return', 'earnings statement', 'adp totalsource', 'paychex flex', 'clinical progress note', 'inpatient discharge summary', 'mri brain', 'closing disclosure', 'settlement statement', 'clinical protocol', 'research strategy', 'deposit in escrow', 'incident record', 'institutional review board', 'review board', 'national institutes', 'institutes health', 'dana-farber', 'cancer institute', 'harvard medical school', 'medical school', 'department homeland security', 'homeland security', 'control sc-28', 'sc-28 attestation', 'system security plan', 'morgan stanley', 'blackstone capital', 'communicating pi',
540
+ 'docket number', 'docket numbers', 'dockets section', 'case name', 'case names', 'case number', 'case numbers', 'law firm', 'law firms', 'counsel stack', 'counselstack', 'counselstack connector', 'tier 0', 'tier 1', 'tier 2', 'tier 3', 'tier 4', 'do not', 'do not write', 'specific permission', 'write again', 'without permission', 'without specific permission', 'on screen', 'in report', 'own line', 'connector access', 'prompt instruction', 'prompt instructions', 'finding report', 'findings report', 'wage and tax statement', 'form w-2', 'wage and tax', 'tax statement', 'u.s. individual', 'income tax return', 'earnings statement', 'adp totalsource', 'paychex flex', 'clinical progress note', 'inpatient discharge summary', 'mri brain', 'closing disclosure', 'settlement statement', 'clinical protocol', 'research strategy', 'deposit in escrow', 'incident record', 'institutional review board', 'review board', 'national institutes', 'institutes health', 'dana-farber', 'cancer institute', 'harvard medical school', 'medical school', 'department homeland security', 'homeland security', 'control sc-28', 'sc-28 attestation', 'system security plan', 'morgan stanley', 'blackstone capital', 'communicating pi', 'contractual clauses', 'standard contractual clauses', 'driver license', 'drivers license', 'improvement plan', 'performance improvement plan', 'vehicle identification', 'custodial portfolio', 'brokerage acct', 'brokerage account', 'settlement agreement', 'retainer agreement', 'service level agreement', 'master services agreement', 'order form', 'statement of work', 'data processing addendum', 'binding corporate rules', 'commercial register', 'board resolution', 'power of attorney', 'letters testamentary', 'letters of administration', 'court docket', 'state bar', 'incident report', 'threat actor', 'mitre att&ck', 'sigma rule', 'security information', 'virtual data room', 'cap table', 'term sheet', 'confidential disclosure',
424
541
  'white bishop', 'black bishop', 'white knight', 'black knight', 'white king', 'black king', 'white queen', 'black queen', 'white rook', 'black rook', 'white pawn', 'black pawn', 'chess piece', 'chess pieces', 'chess game', 'chess match', 'disney-pixar', 'disney pixar', 'pixar animation', 'close-up', 'close up',
425
542
  'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december',
426
543
  'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
@@ -460,12 +577,26 @@ let NAME_STOP_LIST = new Set([
460
577
  , 'quarterly results', 'strategic planning', 'market research', 'customer base', 'privacy settings', 'account settings', 'security settings', 'download now', 'free trial', 'limited time', 'copyright protected', 'all rights', 'rights reserved', 'credit score', 'monthly rent', 'lease application', 'property address', 'reference number', 'additional identifier', 'lease agreement', 'hiring review', 'candidate name', 'privacy policy', 'terms of service', 'machine learning', 'artificial intelligence', 'generative ai', 'silicon valley', 'google cloud', 'amazon web', 'data science', 'operating system', 'software engineer', 'product manager', 'project manager', 'data analyst', 'gross margin', 'revenue growth', 'source code', 'version control', 'large language model',
461
578
  'wages', 'wage', 'tips', 'compensation', 'withheld', 'withholding', 'medicare', 'deductions', 'deduction',
462
579
  'regular', 'hours', 'holiday', 'overtime', 'commission', 'bonus', 'bonuses', 'records', 'record', 'statement', 'statements', 'rate', 'rates', 'current', 'ytd', 'benefits', 'taxable', 'pre-tax', 'post-tax', 'reimbursements', 'reimbursement', 'fica', 'oasdi', 'disability', 'unemployment', 'sui', 'sdi', 'std', 'ltd', 'exemptions', 'exemption', 'allowances', 'allowance', 'filing', 'status', 'single', 'married', 'head', 'household', 'advice', 'frequency', 'bi-weekly', 'biweekly', 'weekly', 'monthly', 'semi-monthly', 'direct', 'deposit', 'routing', 'box', 'boxes', 'code', 'control', 'omb', 'copy', 'instructions', 'information', 'deferred', 'adoption', 'statutory', 'third-party', 'sick', 'form', 'schedule', 'w-2', 'w2', 'w-4', 'w4', '1099', 'k-1', '1040', 'fed', 'med', 'fwt', 'swt', 'fed w/h', 'fed med', 'locality', 'state wages', 'state tax', 'local wages', 'local tax', 'allocated', 'nonqualified', 'suff', 'suffix', 'allocated tips', 'advance eic', 'advance eic payment', 'dependent care', 'dependent care benefits', 'nonqualified plans', 'statutory employee', 'retirement plan', 'third-party sick pay',
463
- 'uk', 'eu', 'us', 'usa', 'dpa', 'ico', 'dpo', 'ciso', 'ssrn', 'elsevier', 'gdpr', 'ccpa', 'cpra', 'hipaa', 'soc2', 'iso27001', 'governance', 'regulatory', 'framework', 'mandate', 'mandates', 'guidance', 'statute', 'statutes', 'jurisdiction', 'jurisdictions', 'recital', 'article', 'articles', 'treatise', 'workstation', 'device', 'endpoint', 'blueprint', 'personal', 'cross-border', 'cross', 'border', 'transfer', 'retrieval', 'augmented', 'generation', 'limitation', 'discrimination', 'imposes', 'heavy', 'identifiable', 'bypasses', 'author', 'contact', 'keywords', 'keyword', 'keys', 'key', 'separation', 'pre-print', 'preprint']);
580
+ 'uk', 'eu', 'us', 'usa', 'dpa', 'ico', 'dpo', 'ciso', 'ssrn', 'elsevier', 'gdpr', 'ccpa', 'cpra', 'hipaa', 'soc2', 'iso27001', 'governance', 'regulatory', 'framework', 'mandate', 'mandates', 'guidance', 'statute', 'statutes', 'jurisdiction', 'jurisdictions', 'recital', 'article', 'articles', 'treatise', 'workstation', 'device', 'endpoint', 'blueprint', 'personal', 'cross-border', 'cross', 'border', 'transfer', 'retrieval', 'augmented', 'generation', 'limitation', 'discrimination', 'imposes', 'heavy', 'identifiable', 'bypasses', 'author', 'authors', 'contact', 'contacts', 'keywords', 'keyword', 'keys', 'key', 'separation', 'pre-print', 'preprint', 'abstract', 'structured', 'background', 'methods', 'results', 'discussion', 'conclusion', 'conclusions', 'introduction', 'overview', 'workflow', 'paradigm', 'nomenclature', 'repository', 'classification', 'phenotypes', 'biomedical', 'bioinformatics', 'identifiers', 'de-identification', 'sanitization', 'ephemeral', 'validation', 'validating', 'genomic', 'genomics', 'clinical', 'phenotype', 'target', 'corresponding', 'subject', 'biorxiv', 'medrxiv', 'arxiv', 'privacyscrubber', 'research', 'lead', 'architect', 'chief', 'founder', 'symbols', 'gene', 'genes', 'sample', 'barcode', 'pipeline', 'downstream', 'pedigree', 'trees', 'exposes', 'violates', 'protecting', 'anonymization', 'redacted', 'redaction', 'zero-trust', 'ztds',
581
+ 'conventional', 'model', 'models', 'potential', 'multi', 'million', 'dollar', 'dollars', 'surrogate', 'surrogates', 'geographic', 'subdivisions', 'subdivision', 'inference', 'response', 'responses', 'latency', 'benchmarks', 'benchmark', 'experimental', 'methodology', 'informatics', 'ethics', 'accountability', 'civil', 'rights', 'perimeter', 'network', 'requirements', 'requirement', 'statutory', 'categories', 'category', 'regulations', 'regulation', 'penalties', 'penalty', 'disclosure', 'disclosures', 'clinician', 'terminal', 'transport', 'inpatient', 'discharge', 'summaries', 'operative', 'reports', 'outpatient', 'psychiatric', 'telehealth', 'consultation', 'pathology', 'sequencing', 'laboratory', 'sensitivity', 'specificity', 'proxy', 'gateways', 'gateway', 'packet', 'packets', 'inspection', 'declarations', 'availability', 'competing', 'interests', 'interventions', 'multicenter', 'multi-center', 'institution', 'institutional', 'protocol', 'deviations', 'adverse', 'events', 'abbreviations', 'agents', 'agent', 'committee', 'committees', 'board', 'boards', 'nih', 'pubmed', 'central', 'open', 'access', 'policy', 'trial', 'trials', 'crf', 'crfs', 'ehr', 'ehrs', 'baa', 'baas', 'hitech', 'safe', 'harbor', 'section']);
582
+
583
+ let JARGON_WORDS = new Set(['step', 'page', 'grade', 'version', 'course', 'class', 'follow', 'chapter', 'lesson', 'unit', 'marketing', 'manager', 'specialist', 'science', 'administration', 'university', 'skills', 'leadership', 'communication', 'working', 'proficiency', 'decision', 'driven', 'experience', 'summary', 'bachelor', 'ads', 'solutions', 'positioning', 'acquisition', 'strategy', 'research', 'database', 'forecast', 'interest', 'prepared', 'merchant', 'document', 'feedback', 'template', 'campaign', 'partners', 'settings', 'keystone', 'llm', 'gpt', 'chatgpt', 'openai', 'anthropic', 'claude', 'gemini', 'api', 'json', 'xml', 'html', 'css', 'javascript', 'python', 'golang', 'typescript', 'rust', 'fastapi', 'snowflake', 'kubernetes', 'terraform', 'docker', 'redis', 'kafka', 'pytorch', 'policy', 'terms', 'conditions', 'release', 'sprint', 'deployment', 'cluster', 'instance', 'package', 'module', 'revenue', 'margin', 'gross', 'quarter', 'system', 'code', 'data', 'cloud', 'server', 'database', 'artificial', 'intelligence', 'learning', 'generative', 'regular', 'hours', 'holiday', 'earnings', 'deductions', 'withheld', 'withholding', 'taxes', 'medicare', 'benefits', 'reimbursements', 'compensation', 'wages', 'code', 'uk', 'eu', 'us', 'usa', 'dpa', 'ico', 'dpo', 'ciso', 'ssrn', 'elsevier', 'gdpr', 'ccpa', 'cpra', 'hipaa', 'soc2', 'iso27001', 'governance', 'regulatory', 'framework', 'mandate', 'mandates', 'guidance', 'statute', 'statutes', 'jurisdiction', 'jurisdictions', 'recital', 'article', 'articles', 'treatise', 'workstation', 'device', 'endpoint', 'blueprint', 'personal', 'cross-border', 'cross', 'border', 'transfer', 'retrieval', 'augmented', 'generation', 'limitation', 'discrimination', 'imposes', 'heavy', 'identifiable', 'bypasses', 'author', 'authors', 'contact', 'contacts', 'keywords', 'keyword', 'keys', 'key', 'separation', 'pre-print', 'preprint', 'abstract', 'structured', 'background', 'methods', 'results', 'discussion', 'conclusion', 'conclusions', 'introduction', 'overview', 'workflow', 'paradigm', 'nomenclature', 'repository', 'classification', 'phenotypes', 'biomedical', 'bioinformatics', 'identifiers', 'de-identification', 'sanitization', 'ephemeral', 'validation', 'validating', 'genomic', 'genomics', 'clinical', 'phenotype', 'target', 'corresponding', 'subject', 'biorxiv', 'medrxiv', 'arxiv', 'privacyscrubber', 'research', 'lead', 'architect', 'chief', 'founder', 'symbols', 'gene', 'genes', 'sample', 'barcode', 'pipeline', 'downstream', 'pedigree', 'trees', 'exposes', 'violates', 'protecting', 'anonymization', 'redacted', 'redaction', 'zero-trust', 'ztds',
584
+ 'conventional', 'model', 'models', 'potential', 'multi', 'million', 'dollar', 'dollars', 'surrogate', 'surrogates', 'geographic', 'subdivisions', 'subdivision', 'inference', 'response', 'responses', 'latency', 'benchmarks', 'benchmark', 'experimental', 'methodology', 'informatics', 'ethics', 'accountability', 'civil', 'rights', 'perimeter', 'network', 'requirements', 'requirement', 'statutory', 'categories', 'category', 'regulations', 'regulation', 'penalties', 'penalty', 'disclosure', 'disclosures', 'clinician', 'terminal', 'transport', 'inpatient', 'discharge', 'summaries', 'operative', 'reports', 'outpatient', 'psychiatric', 'telehealth', 'consultation', 'pathology', 'sequencing', 'laboratory', 'sensitivity', 'specificity', 'proxy', 'gateways', 'gateway', 'packet', 'packets', 'inspection', 'declarations', 'availability', 'competing', 'interests', 'interventions', 'multicenter', 'multi-center', 'institution', 'institutional', 'protocol', 'deviations', 'adverse', 'events', 'abbreviations', 'agents', 'agent', 'committee', 'committees', 'board', 'boards', 'nih', 'pubmed', 'central', 'open', 'access', 'policy', 'trial', 'trials', 'crf', 'crfs', 'ehr', 'ehrs', 'baa', 'baas', 'hitech', 'safe', 'harbor', 'section']);
464
585
 
465
- let JARGON_WORDS = new Set(['step', 'page', 'grade', 'version', 'course', 'class', 'follow', 'chapter', 'lesson', 'unit', 'marketing', 'manager', 'specialist', 'science', 'administration', 'university', 'skills', 'leadership', 'communication', 'working', 'proficiency', 'decision', 'driven', 'experience', 'summary', 'bachelor', 'ads', 'solutions', 'positioning', 'acquisition', 'strategy', 'research', 'database', 'forecast', 'interest', 'prepared', 'merchant', 'document', 'feedback', 'template', 'campaign', 'partners', 'settings', 'keystone', 'llm', 'gpt', 'chatgpt', 'openai', 'anthropic', 'claude', 'gemini', 'api', 'json', 'xml', 'html', 'css', 'javascript', 'python', 'golang', 'typescript', 'rust', 'fastapi', 'snowflake', 'kubernetes', 'terraform', 'docker', 'redis', 'kafka', 'pytorch', 'policy', 'terms', 'conditions', 'release', 'sprint', 'deployment', 'cluster', 'instance', 'package', 'module', 'revenue', 'margin', 'gross', 'quarter', 'system', 'code', 'data', 'cloud', 'server', 'database', 'artificial', 'intelligence', 'learning', 'generative', 'regular', 'hours', 'holiday', 'earnings', 'deductions', 'withheld', 'withholding', 'taxes', 'medicare', 'benefits', 'reimbursements', 'compensation', 'wages', 'code', 'uk', 'eu', 'us', 'usa', 'dpa', 'ico', 'dpo', 'ciso', 'ssrn', 'elsevier', 'gdpr', 'ccpa', 'cpra', 'hipaa', 'soc2', 'iso27001', 'governance', 'regulatory', 'framework', 'mandate', 'mandates', 'guidance', 'statute', 'statutes', 'jurisdiction', 'jurisdictions', 'recital', 'article', 'articles', 'treatise', 'workstation', 'device', 'endpoint', 'blueprint', 'personal', 'cross-border', 'cross', 'border', 'transfer', 'retrieval', 'augmented', 'generation', 'limitation', 'discrimination', 'imposes', 'heavy', 'identifiable', 'bypasses', 'author', 'contact', 'keywords', 'keyword', 'keys', 'key', 'separation', 'pre-print', 'preprint']);
586
+ const US_STATES_SET = new Set([
587
+ 'california', 'texas', 'florida', 'york', 'illinois', 'pennsylvania', 'ohio', 'georgia', 'michigan', 'carolina', 'virginia', 'washington', 'arizona', 'massachusetts', 'tennessee', 'indiana', 'maryland', 'missouri', 'wisconsin', 'colorado', 'minnesota', 'alabama', 'louisiana', 'kentucky', 'oregon', 'oklahoma', 'connecticut', 'utah', 'iowa', 'nevada', 'arkansas', 'mississippi', 'kansas', 'new mexico', 'nebraska', 'idaho', 'hawaii', 'maine', 'new hampshire', 'rhode island', 'montana', 'delaware', 'south dakota', 'north dakota', 'alaska', 'vermont', 'wyoming'
588
+ ]);
589
+
590
+ const CORPORATE_SUFFIXES = new Set([
591
+ 'inc', 'llc', 'corp', 'corporation', 'ltd', 'limited', 'co', 'company',
592
+ 'group', 'holdings', 'solutions', 'services', 'technologies', 'logistics',
593
+ 'industries', 'capital', 'bank', 'partners', 'llp', 'pllc', 'usa'
594
+ ]);
466
595
 
467
596
  let NOT_NAME_WORDS = new Set([
468
- 'uk', 'eu', 'us', 'usa', 'dpa', 'ico', 'dpo', 'ciso', 'ssrn', 'elsevier', 'gdpr', 'ccpa', 'cpra', 'hipaa', 'soc2', 'iso27001', 'governance', 'regulatory', 'framework', 'mandate', 'mandates', 'guidance', 'statute', 'statutes', 'jurisdiction', 'jurisdictions', 'recital', 'article', 'articles', 'treatise', 'workstation', 'device', 'endpoint', 'blueprint', 'personal', 'cross-border', 'cross', 'border', 'transfer', 'retrieval', 'augmented', 'generation', 'limitation', 'discrimination', 'imposes', 'heavy', 'identifiable', 'bypasses', 'author', 'contact', 'keywords', 'keyword', 'keys', 'key', 'separation', 'pre-print', 'preprint',
597
+ 'uk', 'eu', 'us', 'usa', 'dpa', 'ico', 'dpo', 'ciso', 'ssrn', 'elsevier', 'gdpr', 'ccpa', 'cpra', 'hipaa', 'soc2', 'iso27001', 'governance', 'regulatory', 'framework', 'mandate', 'mandates', 'guidance', 'statute', 'statutes', 'jurisdiction', 'jurisdictions', 'recital', 'article', 'articles', 'treatise', 'workstation', 'device', 'endpoint', 'blueprint', 'personal', 'cross-border', 'cross', 'border', 'transfer', 'retrieval', 'augmented', 'generation', 'limitation', 'discrimination', 'imposes', 'heavy', 'identifiable', 'bypasses', 'author', 'authors', 'contact', 'contacts', 'keywords', 'keyword', 'keys', 'key', 'separation', 'pre-print', 'preprint', 'abstract', 'structured', 'background', 'methods', 'results', 'discussion', 'conclusion', 'conclusions', 'introduction', 'overview', 'workflow', 'paradigm', 'nomenclature', 'repository', 'classification', 'phenotypes', 'biomedical', 'bioinformatics', 'identifiers', 'de-identification', 'sanitization', 'ephemeral', 'validation', 'validating', 'genomic', 'genomics', 'clinical', 'phenotype', 'target', 'corresponding', 'subject', 'biorxiv', 'medrxiv', 'arxiv', 'privacyscrubber', 'research', 'lead', 'architect', 'chief', 'founder', 'symbols', 'gene', 'genes', 'sample', 'barcode', 'pipeline', 'downstream', 'pedigree', 'trees', 'exposes', 'violates', 'protecting', 'anonymization', 'redacted', 'redaction', 'zero-trust', 'ztds',
598
+ 'conventional', 'model', 'models', 'potential', 'multi', 'million', 'dollar', 'dollars', 'surrogate', 'surrogates', 'geographic', 'subdivisions', 'subdivision', 'inference', 'response', 'responses', 'latency', 'benchmarks', 'benchmark', 'experimental', 'methodology', 'informatics', 'ethics', 'accountability', 'civil', 'rights', 'perimeter', 'network', 'requirements', 'requirement', 'statutory', 'categories', 'category', 'regulations', 'regulation', 'penalties', 'penalty', 'disclosure', 'disclosures', 'clinician', 'terminal', 'transport', 'inpatient', 'discharge', 'summaries', 'operative', 'reports', 'outpatient', 'psychiatric', 'telehealth', 'consultation', 'pathology', 'sequencing', 'laboratory', 'sensitivity', 'specificity', 'proxy', 'gateways', 'gateway', 'packet', 'packets', 'inspection', 'declarations', 'availability', 'competing', 'interests', 'interventions', 'multicenter', 'multi-center', 'institution', 'institutional', 'protocol', 'deviations', 'adverse', 'events', 'abbreviations', 'agents', 'agent', 'committee', 'committees', 'board', 'boards', 'nih', 'pubmed', 'central', 'open', 'access', 'policy', 'trial', 'trials', 'crf', 'crfs', 'ehr', 'ehrs', 'baa', 'baas', 'hitech', 'safe', 'harbor', 'section',
599
+ 'retirement', 'roth', 'ira', 'acct', 'custodial', 'brokerage', 'portfolio', 'annuity', 'dividend', 'distribution', 'reconciliation', 'withholding', 'remuneration', 'pin', 'lobby', 'passcode', 'code', 'gate', 'door', 'access', 'tenant', 'landlord', 'escrow', 'cadastral', 'claim', 'claims', 'adjuster', 'insured', 'carrier', 'indemnity', 'underwriter', 'underwriting', 'deductible', 'premium', 'settlement', 'loss', 'cargo', 'writers', 'guild', 'ghostwriter', 'actor', 'screenplay', 'audiovisual', 'cinematic', 'co-production', 'alumnus', 'alumni', 'registrar', 'transcript', 'diploma', 'orchestration', 'runtime', 'helpdesk', 'freshdesk', 'intercom', 'zendesk', 'investigational', 'pharmacovigilance', 'reaction', 'medication', 'manufacturing', 'lot', 'industrial', 'electronics', 'driver', 'drivers', 'license', 'licence', 'clearing', 'house', 'automated', 'central', 'securities', 'depository', 'arbitration', 'tribunal', 'instrument', 'infrastructure', 'talent', 'dossier',
469
600
  // Grammatical & Sentence Starters
470
601
  'the', 'a', 'an', 'this', 'that', 'these', 'those', 'my', 'your', 'his', 'her', 'their', 'our', 'its', 'it', 'he', 'she', 'they', 'we', 'i', 'you', 'who', 'whom', 'which', 'what', 'whose', 'why', 'how', 'when', 'where', 'with', 'for', 'from', 'by', 'to', 'at', 'in', 'on', 'of', 'about', 'as', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'and', 'but', 'or', 'so', 'yet', 'im', "i'm", "you're", "they're", "we're", "it's", "he's", "she's", "that's", "there's", "what's", "who's", "i've", "you've", "we've", "they've", "i'll", "you'll", "we'll", "they'll", "i'd", "you'd", "we'd", "they'd",
471
602
  // Verbs, Auxiliaries, Commands & Imperatives
@@ -569,6 +700,7 @@ let NOT_NAME_WORDS = new Set([
569
700
 
570
701
  // General Academic & Professional vocabulary
571
702
  'bachelor', 'master', 'doctor', 'associate', 'degree', 'university', 'college', 'school', 'institute', 'academy', 'graduated', 'major', 'minor', 'gpa', 'cum', 'laude', 'honors', 'deans', 'list', 'scholarship',
703
+ 'language', 'model', 'models', 'llm', 'llms', 'genetic', 'genetics', 'special', 'category', 'categories', 'variant', 'variants', 'allele', 'alleles', 'frequency', 'frequencies', 'chromosome', 'chromosomes', 'mutation', 'mutations', 'phenotype', 'phenotypes', 'expression', 'annotation', 'annotations', 'genomic', 'genomics', 'molecular', 'sequence', 'sequencing', 'reference', 'dataset', 'datasets',
572
704
  // Quality & Adjectives
573
705
  'results', 'driven', 'oriented', 'expert', 'professional', 'proven', 'track', 'record', 'creative', 'excellent', 'communication', 'verbal', 'written', 'native', 'fluent', 'bilingual', 'working', 'proficiency', 'strategic', 'interpersonal', 'teamwork', 'organizational', 'detail', 'analytical',
574
706
  // Common Resume / Business Phrases
@@ -704,8 +836,8 @@ const PROFILE_JARGON = {
704
836
  'general': 'general',
705
837
  'underwriting': 'underwriting', 'lending': 'underwriting', 'mortgage': 'underwriting', 'loan': 'underwriting', 'income': 'underwriting', 'income_verification': 'underwriting', 'payroll': 'underwriting', 'w2': 'underwriting', 'paystub': 'underwriting',
706
838
  'medical': 'medical', 'healthcare': 'medical', 'health': 'medical', 'pharma': 'pharma', 'hipaa': 'medical',
707
- 'engineering': 'engineering', 'dev': 'engineering', 'devops': 'engineering', 'tech': 'tech',
708
- 'finance': 'finance', 'bizops': 'bizops', 'sales': 'sales', 'wealthmgmt': 'wealthmgmt', 'wealth': 'wealthmgmt', 'insurance': 'insurance', 'accounting': 'accounting', 'pci': 'finance',
839
+ 'engineering': 'engineering', 'dev': 'dev', 'api': 'dev', 'devops': 'engineering', 'tech': 'tech',
840
+ 'finance': 'finance', 'financial': 'finance', 'bizops': 'bizops', 'sales': 'sales', 'wealthmgmt': 'wealthmgmt', 'wealth': 'wealthmgmt', 'insurance': 'insurance', 'accounting': 'accounting', 'pci': 'finance',
709
841
  'legal': 'legal', 'compliance': 'compliance', 'ccpa': 'ccpa', 'gdpr': 'compliance', 'soc2': 'compliance', 'iso27001': 'compliance', 'nist': 'compliance', 'dpo': 'compliance', 'grc': 'compliance',
710
842
  'hr': 'hr', 'security': 'security', 'marketing': 'marketing', 'support': 'support',
711
843
  'realestate': 'realestate', 'academic': 'academic', 'agents': 'agents', 'ai_agents': 'agents', 'creative': 'creative', 'personal': 'personal'
@@ -723,17 +855,19 @@ const PROFILE_JARGON = {
723
855
  }
724
856
 
725
857
  function stitchOrphanedNameLines(text, profile) {
726
- if (profile === 'medical') {
727
- text = text.replace(/Patient Name:\s*\n+([A-Z][a-zA-Z]+\s[A-Z][a-zA-Z]+)/g, 'Patient Name: $1');
728
- } else if (profile === 'legal') {
729
- text = text.replace(/Defendant:\s*\n+([A-Z][a-zA-Z]+\s[A-Z][a-zA-Z]+)/g, 'Defendant: $1');
858
+ if (!text || !text.includes('\n')) return text;
859
+ const prof = (profile || 'general').toLowerCase();
860
+ if (prof === 'medical' || prof === 'general') {
861
+ text = text.replace(/(Patient\s+Name|Emergency\s+Contact|In\s+Case\s+of\s+Emergency|ICE(?:\s+Contact)?):\s*\r?\n+([A-Z\p{Lu}][A-Za-z0-9&.,'’ \t-]*?[A-Za-z0-9\p{Lu}\p{Ll}])(?=\r?\n|$)/gui, '$1: $2');
862
+ } else if (prof === 'legal') {
863
+ text = text.replace(/Defendant:\s*\r?\n+([A-Z][a-zA-Z]+\s[A-Z][a-zA-Z]+)/g, 'Defendant: $1');
730
864
  }
731
865
  return text;
732
866
  }
733
867
 
734
868
  function detectMatches(text, activeProfile = 'general', customRules = [], nlpNames = [], enabledEntities = null, mlEntities = []) {
735
- let textToProcess = text.replace(/[\u200b\u200c\u200d\ufeff]/g, '');
736
- textToProcess = textToProcess.replace(/([a-zA-Z])(Email|Phone|Mobile|Tel|Address|IP|ID|URL|SSN|Date):/g, '$1 $2:');
869
+ let textToProcess = stitchOrphanedNameLines(text, activeProfile).replace(/[\u200b\u200c\u200d\ufeff]/g, '');
870
+ textToProcess = textToProcess.replace(/([a-z])(Email|Phone|Mobile|Tel|Address|IP|ID|URL|SSN|Date):/g, '$1 $2:');
737
871
 
738
872
  let matches = [];
739
873
 
@@ -795,7 +929,7 @@ const PROFILE_JARGON = {
795
929
 
796
930
  if (rule.type !== 'NAME' && rule.type !== 'ADDRESS') {
797
931
  const val = matchedText.toLowerCase().trim();
798
- if (NAME_STOP_LIST.has(val) || NOT_NAME_WORDS.has(val) || currentJargon.has(val)) {
932
+ if (NOT_NAME_WORDS.has(val) || currentJargon.has(val)) {
799
933
  // Skip if generic English dictionary term matched by greedy regex (e.g. SWIFT matching SCRUBBER or CONTAINS)
800
934
  if (rule.type === 'FINANCIAL' || rule.type === 'ID' || rule.type === 'PRIVACY' || rule.type === 'SECRET' || rule.type === 'LEGAL' || rule.type === 'PHI') {
801
935
  continue;
@@ -839,8 +973,20 @@ const PROFILE_JARGON = {
839
973
  })
840
974
  )) continue;
841
975
 
842
- if (rule.isContextName && words.length > 0 && words.every(w => {
976
+ if (rule.isAggressiveName) {
977
+ const lineStart = textToProcess.lastIndexOf('\n', start) + 1;
978
+ const lineEnd = textToProcess.indexOf('\n', end);
979
+ const fullLine = textToProcess.substring(lineStart, lineEnd === -1 ? textToProcess.length : lineEnd).trim();
980
+ if (fullLine.startsWith('|') || fullLine.startsWith('+') || fullLine.includes('===') || fullLine.includes('---')) {
981
+ continue;
982
+ }
983
+ }
984
+
985
+ if (rule.isContextName && words.length > 0 && words.some(w => {
843
986
  const cleanW = w.replace(/[^\p{L}]/gu, '');
987
+ if (rule.isCorporateName && (CORPORATE_SUFFIXES.has(cleanW) || US_STATES_SET.has(cleanW))) {
988
+ return false;
989
+ }
844
990
  return !cleanW || currentJargon.has(w) || NOT_NAME_WORDS.has(w) || NOT_NAME_WORDS.has(cleanW) || NAME_STOP_LIST.has(w) || NAME_STOP_LIST.has(cleanW);
845
991
  })) {
846
992
  continue;
@@ -850,7 +996,7 @@ const PROFILE_JARGON = {
850
996
  if (NAME_STOP_LIST.has(cleanVal) || currentJargon.has(cleanVal) || NOT_NAME_WORDS.has(cleanVal)) continue;
851
997
  }
852
998
 
853
- matches.push({ start, end: start + matchedText.length, value: matchedText, type: rule.type });
999
+ matches.push({ start, end: start + matchedText.length, value: matchedText, type: rule.type, isHighConfidence: !!rule.isContextName });
854
1000
  }
855
1001
  }
856
1002
  });
@@ -861,12 +1007,15 @@ const PROFILE_JARGON = {
861
1007
  const val = name.toLowerCase().trim();
862
1008
  if (NAME_STOP_LIST.has(val) || NOT_NAME_WORDS.has(val) || currentJargon.has(val)) return;
863
1009
  const words = val.split(/\s+/);
864
- if (words.every(w => NOT_NAME_WORDS.has(w) || currentJargon.has(w) || NAME_STOP_LIST.has(w))) return;
1010
+ if (words.some(w => {
1011
+ const cleanW = w.replace(/[^\p{L}]/gu, '');
1012
+ return !cleanW || NOT_NAME_WORDS.has(w) || NOT_NAME_WORDS.has(cleanW) || currentJargon.has(w) || currentJargon.has(cleanW) || NAME_STOP_LIST.has(w) || NAME_STOP_LIST.has(cleanW);
1013
+ })) return;
865
1014
  const safeName = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
866
1015
  const rx = new RegExp(`(?<=^|[^\\p{L}\\p{N}_])${safeName}(?=[^\\p{L}\\p{N}_]|$)`, 'gu');
867
1016
  let m;
868
1017
  while ((m = rx.exec(textToProcess)) !== null) {
869
- matches.push({ start: m.index, end: m.index + m[0].length, value: m[0], type: 'NAME' });
1018
+ matches.push({ start: m.index, end: m.index + m[0].length, value: m[0], type: 'NAME', isHighConfidence: true });
870
1019
  }
871
1020
  });
872
1021
  }
@@ -877,14 +1026,14 @@ const PROFILE_JARGON = {
877
1026
  const rx = new RegExp(`(?<=^|[^\\p{L}\\p{N}_])${safeName}(?=[^\\p{L}\\p{N}_]|$)`, 'giu');
878
1027
  let m;
879
1028
  while ((m = rx.exec(textToProcess)) !== null) {
880
- matches.push({ start: m.index, end: m.index + m[0].length, value: m[0], type: item.type });
1029
+ matches.push({ start: m.index, end: m.index + m[0].length, value: m[0], type: item.type, isHighConfidence: true });
881
1030
  }
882
1031
  });
883
1032
  }
884
1033
 
885
1034
  const learnedNames = new Set();
886
1035
  matches.forEach(m => {
887
- if (m.type === 'NAME') {
1036
+ if (m.type === 'NAME' && m.isHighConfidence) {
888
1037
  const nameWords = m.value.split(/[^\p{L}'-]+/u);
889
1038
  nameWords.forEach(w => {
890
1039
  if (w && w.length >= 2 && /^\p{Lu}/u.test(w)) {
@@ -1025,7 +1174,7 @@ const PROFILE_JARGON = {
1025
1174
  cleaned = cleaned.replace(/(?:^|\n)[a-zA-Z0-9_#.:\-*>[\]=\s,'"]+\{[^}]*(--[a-zA-Z0-9_-]+:|color-mix\(|var\()[^}]*\}/g, "");
1026
1175
  }
1027
1176
  // 2. Strip AI author prefixes and platform artifacts
1028
- cleaned = cleaned.replace(/^\s*(?:Claude responded|Claude|ChatGPT|Gemini|Grok|DeepSeek|Kimi|Copilot|Assistant|User)\s*(?::|\bsaid\b|\bresponded\b|(?=\s))\s*/i, "");
1177
+ cleaned = cleaned.replace(/^\s*(?:Claude responded|Claude|ChatGPT|Gemini|Grok|DeepSeek|Kimi|Copilot|Assistant|User)\s*(?::|\bsaid\b|\bresponded\b|(?:\s*\n))\s*/i, "");
1029
1178
  cleaned = cleaned.replace(/^(?:Here (?:is|are) (?:the )?(?:redacted|scrubbed|sanitized|processed|clean|updated|modified) (?:text|output|version|data).*?[:\n]+|\*\*Scrubbed Text\*\*[:\n]+|### Scrubbed Text[:\n]+)/i, '');
1030
1179
  cleaned = cleaned.replace(/^\s*Edit\s*\n+/i, "");
1031
1180
  cleaned = cleaned.replace(/\s*\bEdit\s+in\s+a\s+page\b\s*$/i, "");