Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
## [unreleased]

### Analyzer
#### Added
- Added `NgBvnRecognizer` for Nigerian Bank Verification Numbers (`NG_BVN`). The BVN is an 11-digit identifier issued by the CBN and managed by NIBSS. No public checksum is documented; confidence is context-driven via `LemmaContextAwareEnhancer`. Registered in `default_recognizers.yaml` (disabled by default). (#2169, Thanks @kingztech2019)
- Added `KeNationalIdRecognizer` for Kenyan National Identity Card numbers (`KE_NATIONAL_ID`). The card number is a 7- or 8-digit identifier issued by the National Registration Bureau. No public checksum is documented; confidence is context-driven. Registered in `default_recognizers.yaml` (disabled by default). (#2169, Thanks @kingztech2019)

#### Fixed
- `PhoneRecognizer.DEFAULT_SUPPORTED_REGIONS` used `"UK"`, which is not a valid `phonenumbers` (libphonenumber) region code — region codes are ISO 3166-1 alpha-2, where the United Kingdom is `"GB"`. The `"UK"` entry was a no-op, so UK numbers in national/local format (e.g. `020 7946 0958`) were never detected by default; only international-format `+44 …` numbers matched, because they carry the country code and match under any region. Replaced `"UK"` with `"GB"`.
- Language model recognizers (`BasicLangExtractRecognizer`, `AzureOpenAILangExtractRecognizer`) configured in a recognizer registry YAML now honour `config_path` (and other recognizer-specific kwargs). Previously these entries were validated by the strict `PredefinedRecognizerConfig` schema, which has no `config_path` field and does not allow extra keys, so `config_path` was silently dropped and the recognizer fell back to its bundled default model configuration. Added a `LangExtractRecognizerConfig` model (`extra="allow"`) and registered both recognizer class names in `CONFIG_MODEL_MAP`.
Expand Down
6 changes: 6 additions & 0 deletions docs/supported_entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,14 @@ For more information, refer to the [adding new recognizers documentation](analyz
| FieldType | Description | Detection Method |
|------------|---------------------------------------------------------------------------------------------------------|------------------------------------------|
| NG_NIN | The Nigerian National Identification Number (NIN) is a unique 11-digit number issued by the National Identity Management Commission (NIMC). | Pattern match, context, and checksum |
| NG_BVN | The Nigerian Bank Verification Number (BVN) is an 11-digit identifier issued by the Central Bank of Nigeria (CBN) and managed by NIBSS. It links every bank account held by an individual to a single biometric record. No public checksum algorithm is documented; confidence is context-driven. | Pattern match and context |
| NG_VEHICLE_REGISTRATION | Nigerian vehicle registration plate number in the current format (2011+): 3 letters (LGA code), 3 digits (serial), 2 letters (year/batch). | Pattern match and context |

### Kenya
| FieldType | Description | Detection Method |
|------------|---------------------------------------------------------------------------------------------------------|------------------------------------------|
| KE_NATIONAL_ID | The Kenyan National Identity Card number is a 7- or 8-digit sequential identifier issued by the National Registration Bureau under the Registration of Persons Act (Cap. 107). No public checksum algorithm is documented; confidence is context-driven. | Pattern match and context |

### Philippines
| FieldType | Description | Detection Method |
|------------|---------------------------------------------------------------------------------------------------------|------------------------------------------|
Expand Down
14 changes: 14 additions & 0 deletions presidio-analyzer/presidio_analyzer/conf/default_recognizers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,27 @@ recognizers:
enabled: false
country_code: ng

- name: NgBvnRecognizer
supported_languages:
- en
type: predefined
enabled: false
country_code: ng
Comment on lines +184 to +189

- name: InPanRecognizer
supported_languages:
- en
type: predefined
enabled: false
country_code: in

- name: KeNationalIdRecognizer
supported_languages:
- en
type: predefined
enabled: false
country_code: ke

- name: InAadhaarRecognizer
supported_languages:
- en
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,15 @@
from .country_specific.korea.kr_rrn_recognizer import KrRrnRecognizer

# Nigeria recognizers
from .country_specific.nigeria.ng_bvn_recognizer import NgBvnRecognizer
from .country_specific.nigeria.ng_nin_recognizer import NgNinRecognizer
from .country_specific.nigeria.ng_vehicle_registration_recognizer import (
NgVehicleRegistrationRecognizer,
)

# Kenya recognizers
from .country_specific.kenya.ke_national_id_recognizer import KeNationalIdRecognizer

# Philippines recognizers
from .country_specific.philippines.ph_tin_recognizer import PhTinRecognizer
from .country_specific.philippines.ph_umid_recognizer import PhUmidRecognizer
Expand Down Expand Up @@ -255,6 +259,8 @@
"AzureOpenAILangExtractRecognizer",
"BasicLangExtractRecognizer",
"KrPassportRecognizer",
"KeNationalIdRecognizer",
"NgBvnRecognizer",
"NgNinRecognizer",
"NgVehicleRegistrationRecognizer",
"MedicalNERRecognizer",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Kenya-specific recognizers."""

from .ke_national_id_recognizer import KeNationalIdRecognizer

__all__ = [
"KeNationalIdRecognizer",
]

Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from typing import List, Optional

from presidio_analyzer import Pattern, PatternRecognizer


class KeNationalIdRecognizer(PatternRecognizer):
"""
Recognizes Kenyan National Identity Card numbers.

The Kenyan National Identity Card (ID card) is issued by the National
Registration Bureau under the Registration of Persons Act (Cap. 107).
The card number is a 7- or 8-digit sequential identifier unique to each
cardholder. Cards issued since the late 1990s typically carry an 8-digit
number; earlier cards may have 7 digits.

No checksum algorithm is publicly documented for Kenyan national ID
numbers. Confidence is therefore driven primarily by context words.
Without context the base score (0.01) is intentionally low enough to be
filtered by callers applying a reasonable minimum threshold (e.g. 0.35).

Reference: https://www.ecitizen.go.ke/

:param patterns: List of patterns to be used by this recognizer
:param context: List of context words to increase confidence in detection
:param supported_language: Language this recognizer supports
:param supported_entity: The entity this recognizer can detect
"""

COUNTRY_CODE = "ke"

# 7- or 8-digit national ID number, not embedded in a longer number.
PATTERNS = [
Pattern(
"KE National ID (Very Weak)",
r"\b\d{7,8}\b",
0.01,
),
]

CONTEXT = [
# Single-token entries — matched against individual spaCy lemmas by
# LemmaContextAwareEnhancer (substring mode). Multi-word phrases alone
# are never matched because the enhancer compares against single tokens.
"kenya",
"kenyan",
"national",
"nid",
"registration",
# Multi-word entries — only effective when the enhancer is given
# pre-tokenised context via the `context` parameter.
"national id",
"national identity",
"national identity card",
"id number",
"kenyan id",
"kenya national id",
"registration number",
"id card",
"national registration",
]

def __init__(
self,
patterns: Optional[List[Pattern]] = None,
context: Optional[List[str]] = None,
supported_language: str = "en",
supported_entity: str = "KE_NATIONAL_ID",
name: Optional[str] = None,
) -> None:
patterns = patterns if patterns else self.PATTERNS
context = context if context else self.CONTEXT
super().__init__(
supported_entity=supported_entity,
patterns=patterns,
context=context,
supported_language=supported_language,
name=name,
)

def validate_result(self, pattern_text: str) -> Optional[bool]:
"""
Validate basic Kenyan national ID format.

Returns False (and removes the result) if the match is not 7 or 8
numeric digits. Returns None to preserve the context-boosted score
rather than unconditionally promoting to MAX_SCORE, since no checksum
is available to justify that level of certainty.
"""
if not pattern_text.isnumeric() or len(pattern_text) not in (7, 8):
return False
return None
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"""Nigeria-specific recognizers."""

from .ng_bvn_recognizer import NgBvnRecognizer
from .ng_nin_recognizer import NgNinRecognizer
from .ng_vehicle_registration_recognizer import NgVehicleRegistrationRecognizer

__all__ = [
"NgBvnRecognizer",
"NgNinRecognizer",
"NgVehicleRegistrationRecognizer",
]

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from typing import List, Optional

from presidio_analyzer import Pattern, PatternRecognizer


class NgBvnRecognizer(PatternRecognizer):
"""
Recognizes Nigerian Bank Verification Number (BVN).

The BVN is an 11-digit identifier issued by the Central Bank of Nigeria
(CBN) and managed by the Nigerian Interbank Settlement System (NIBSS).
It links every bank account held by an individual to a single biometric
identity record. Unauthorized access to, use of, or disclosure of a BVN
is an offence under the CBN BVN Regulatory Framework (CBN Circular
Ref: FPR/DIR/GEN/CIR/01/009, 2014).

Unlike the Nigerian NIN, the BVN does not have a publicly documented
checksum algorithm. Confidence is therefore driven primarily by context
words rather than structural validation. Without context the base pattern
score (0.01) is low enough to be filtered by callers applying a reasonable
minimum score threshold (e.g. 0.35).

Reference: https://www.cbn.gov.ng/bvn/

:param patterns: List of patterns to be used by this recognizer
:param context: List of context words to increase confidence in detection
:param supported_language: Language this recognizer supports
:param supported_entity: The entity this recognizer can detect
"""

COUNTRY_CODE = "ng"

PATTERNS = [
Pattern(
"BVN (Very Weak)",
r"\b\d{11}\b",
0.01,
),
]

CONTEXT = [
"bvn",
"bank verification number",
"bank verification no",
"bank verification",
"nibss",
"nigeria bank id",
"bank identity number",
]

def __init__(
self,
patterns: Optional[List[Pattern]] = None,
context: Optional[List[str]] = None,
supported_language: str = "en",
supported_entity: str = "NG_BVN",
name: Optional[str] = None,
) -> None:
patterns = patterns if patterns else self.PATTERNS
context = context if context else self.CONTEXT
super().__init__(
supported_entity=supported_entity,
patterns=patterns,
context=context,
supported_language=supported_language,
name=name,
)

def validate_result(self, pattern_text: str) -> Optional[bool]:
"""
Validate basic BVN format.

Returns False (and removes the result) if the match is not exactly 11
numeric digits. Returns None — rather than True — to preserve the
context-boosted score instead of unconditionally promoting it to
MAX_SCORE, since there is no checksum to provide that level of
certainty.
"""
if len(pattern_text) != 11 or not pattern_text.isnumeric():
return False
# Valid format; let context enrichment determine final confidence.
return None
Loading