Class: Phronomy::Guardrail::Builtin::PIIPatternDetector
- Inherits:
-
InputGuardrail
- Object
- Phronomy::Guardrail::Base
- InputGuardrail
- Phronomy::Guardrail::Builtin::PIIPatternDetector
- Defined in:
- lib/phronomy/guardrail/builtin/pii_pattern_detector.rb
Overview
Input guardrail that detects common PII patterns in the input string.
Four categories are supported and each can be individually toggled:
- +:my_number+ — Japanese My Number (12-digit national ID)
- +:credit_card+ — Credit / debit card numbers
- +:email+ — E-mail addresses
- +:phone+ — Japanese domestic phone numbers
All four categories are active by default.
Constant Summary collapse
- PATTERNS =
Recognised PII categories and their detection patterns.
{ # Japanese My Number: 12 consecutive or grouped digits (4-4-4). # Matched candidates are additionally validated with the official check-digit # algorithm (JIS X 0076) to eliminate false positives from arbitrary 12-digit strings. my_number: { pattern: /(?<!\d)(?<!\d[- ])\d{4}[- ]?\d{4}[- ]?\d{4}(?![- ]?\d)/, label: "My Number", validate_my_number: true }, # Credit / debit card: 16 digits, optionally separated by spaces or hyphens. # Matched candidates are additionally validated with the Luhn algorithm # to eliminate false positives from arbitrary 16-digit sequences. credit_card: { pattern: /\b(?:\d{4}[- ]?){3}\d{4}\b/, label: "credit card number", validate_luhn: true }, # Email address (simplified RFC 5322). email: { pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/, label: "email address" }, # Japanese phone number: starts with 0, groups of 2-5 / 1-4 / 4 digits. phone: { pattern: /\b0\d{1,4}[- ]?\d{1,4}[- ]?\d{4}\b/, label: "phone number" } }.freeze
- ALL_CATEGORIES =
PATTERNS.keys.freeze
Instance Method Summary collapse
- #check(value) ⇒ Object
-
#initialize(detect: ALL_CATEGORIES) ⇒ PIIPatternDetector
constructor
A new instance of PIIPatternDetector.
Methods inherited from Phronomy::Guardrail::Base
Constructor Details
#initialize(detect: ALL_CATEGORIES) ⇒ PIIPatternDetector
Returns a new instance of PIIPatternDetector.
60 61 62 63 64 65 |
# File 'lib/phronomy/guardrail/builtin/pii_pattern_detector.rb', line 60 def initialize(detect: ALL_CATEGORIES) unknown = Array(detect) - ALL_CATEGORIES raise ArgumentError, "Unknown PII categories: #{unknown.inspect}" if unknown.any? @active_patterns = Array(detect).map { |cat| PATTERNS.fetch(cat) } end |
Instance Method Details
#check(value) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/phronomy/guardrail/builtin/pii_pattern_detector.rb', line 70 def check(value) text = value.to_s @active_patterns.each do |entry| detected = if entry[:validate_luhn] # Scan for all candidates then filter by Luhn check-digit validation. # This avoids false positives on arbitrary 16-digit strings (e.g. internal IDs). text.scan(entry[:pattern]).any? { |m| luhn_valid?(m.gsub(/[- ]/, "")) } elsif entry[:validate_my_number] # Scan for all candidates then apply the JIS X 0076 check-digit algorithm. # This avoids false positives on arbitrary 12-digit strings. text.scan(entry[:pattern]).any? { |m| my_number_valid?(m.gsub(/[- ]/, "")) } else text.match?(entry[:pattern]) end fail!("PII detected in input: #{entry[:label]}") if detected end end |