| """PII 基礎掃描(L4 minimal;L8 才完整 4 層)。 | |
| 對應 PRD §49 layer 1:regex 即時偵測。先給 5 條內建。 | |
| """ | |
| from __future__ import annotations | |
| import re | |
| # 內建最小規則集(PRD §49 layer 1 預設) | |
| _BUILTIN_PATTERNS = [ | |
| ("台灣身分證", re.compile(r"\b[A-Z][12]\d{8}\b")), | |
| ("手機號碼", re.compile(r"\b09\d{2}[-\s]?\d{3}[-\s]?\d{3}\b")), | |
| ("信用卡號", re.compile(r"\b(?:\d[ -]*?){13,19}\b")), | |
| ("Email 地址", re.compile(r"\b[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}\b")), | |
| ("出生日期", re.compile(r"\b(19|20)\d{2}[-/](0[1-9]|1[0-2])[-/](0[1-9]|[12]\d|3[01])\b")), | |
| ] | |
| def scan(text: str) -> dict | None: | |
| """回傳第一個命中的規則資訊;無命中回 None。""" | |
| if not text: | |
| return None | |
| for name, pat in _BUILTIN_PATTERNS: | |
| m = pat.search(text) | |
| if m: | |
| return { | |
| "layer": 1, | |
| "rule": name, | |
| "match": m.group(0)[:32], | |
| "start": m.start(), | |
| "end": m.end(), | |
| } | |
| return None | |