arche.detect¶
Per-country PII / identity detectors. Each launch jurisdiction exposes an ids module with a single entry function taking only text and returning list[NationalID].
from arche.detect.ng.ids import detect_nigerian_ids
from arche.detect.ke.ids import detect_kenyan_ids
from arche.detect.za.ids import detect_south_african_ids
from arche.detect.gh.ids import detect_ghanaian_ids
For pan-African coverage (RW, TZ, UG, ET, CI, SN, CM, EG, MA, AO, MZ):
from arche.detect._africa.ids import detect_african_ids
from arche.detect._africa.phones import normalize_e164, validate_phone
These per-country detectors return NationalID objects - a lighter record than the
Detection the Pipeline emits. Fields: text, country,
id_type, confidence, start, end, metadata:
from arche.detect.ng.ids import detect_nigerian_ids
detect_nigerian_ids("NIN 12345678901, BVN 22156789012.")[0]
# NationalID(text='22156789012', country='NG', id_type='BVN', confidence=0.85,
# start=21, end=32, metadata={'validator_status': 'format_valid'})
Run the same text through Pipeline to get Detection objects carrying the
Pan-African PII Taxonomy v0.1
category label, the sensitivity tier, and the statute citation.
Most callers don't need this surface directly -
Pipeline(jurisdiction=...)calls the right detectors automatically. Use these primitives when you're building your own composition.
Launch jurisdictions¶
| Country | Module | IDs covered |
|---|---|---|
| NG Nigeria | arche.detect.ng.ids |
NIN, BVN, TIN, RC number, voter PVC, driver's licence |
| KE Kenya | arche.detect.ke.ids |
National ID, KRA PIN, NHIF |
| ZA South Africa | arche.detect.za.ids |
SA ID (full Luhn + DOB/gender/citizenship decode), tax reference, passport |
| GH Ghana | arche.detect.gh.ids |
Ghana Card, SSNIT, TIN |
Non-launch African countries¶
arche.detect._africa.ids.detect_african_ids(text) covers: RW, TZ, UG, ET, CI, SN, CM, EG, MA, AO, MZ. It takes only text - there is no country parameter; the country is inferred and reported on each returned NationalID.country.
Country-specific coverage promotes to a top-level arche.detect.<cc> module as Stage 2 work - based on launch-partner deployments.
Phone normalization¶
from arche.detect._africa.phones import normalize_e164, validate_phone
normalize_e164("0803 555 7890", default_country="NG")
# '+2348035557890'
validate_phone("+254 712 345 678", default_country="KE")
# {'valid': True,
# 'country': 'KE',
# 'e164': '+254712345678',
# 'national': '0712 345678',
# 'international': '+254 712 345678',
# 'country_calling_code': 254,
# 'line_type': 'mobile',
# 'carrier_hint': 'Safaricom',
# 'region_hint': 'Kenya'}
The keyword is default_country, not country, and it defaults to "NG".
normalize_e164 returns str | None; validate_phone returns a dict, not a
tuple.
Wraps the phonenumbers Python port of libphonenumber. Covers 30+ African telecom networks per PRD FR-DETECT-9.
Optional ML backends¶
The GLiNER2 NER backend is available behind the [detect] extra:
There is no public API under arche.detect.gliner or arche.detect.presidio -
both packages are empty placeholder namespaces in this release. import
arche.detect.gliner succeeds but the module exports nothing, so any
from arche.detect.gliner import ... line raises ImportError.
The optional backends are wired in through backend= on the extraction entry
point instead:
from arche.extract import extract
extract("Call 0803 555 7890", backend="regex")
# [EntityReference(text='080***', type='PHONE', confidence=0.90, source='african')]
extract(text, backend="gliner") # raises ModuleNotFoundError without [detect]
backend accepts "auto" (default - GLiNER when installed, regex otherwise),
"auto+llm", "gliner", and "regex". Presidio is reached through
arche.protect, which uses it when installed and falls back to regex when it is
not; it has no arche.detect.presidio surface.
Future model-backed detectors will be documented when they are ready for public evaluation.