Module: Philiprehberger::Mask

Defined in:
lib/philiprehberger/mask.rb,
lib/philiprehberger/mask/version.rb,
lib/philiprehberger/mask/detector.rb,
lib/philiprehberger/mask/scrubber.rb,
lib/philiprehberger/mask/configuration.rb,
lib/philiprehberger/mask/deep_scrubber.rb

Defined Under Namespace

Modules: DeepScrubber, Detector, Scrubber Classes: Configuration, Error

Constant Summary collapse

VERSION =
'0.4.0'

Class Method Summary collapse

Class Method Details

.add_locale(locale, patterns) ⇒ Object

Register locale-specific patterns

Parameters:

  • locale (Symbol)

    locale identifier

  • patterns (Hash<Symbol, Regexp>)

    detector name to regex mapping



93
94
95
# File 'lib/philiprehberger/mask.rb', line 93

def self.add_locale(locale, patterns)
  Configuration.instance.add_locale(locale, patterns)
end

.batch_scrub(strings, mode: :full, locale: nil) ⇒ Array<String>

Process an array of strings in one call with shared compiled patterns

Parameters:

  • strings (Array<String>)

    input strings

  • mode (Symbol) (defaults to: :full)

    masking mode (:full, :partial, :format_preserving)

  • locale (Symbol, nil) (defaults to: nil)

    optional locale for locale-specific patterns

Returns:

  • (Array<String>)

    scrubbed strings



76
77
78
79
80
# File 'lib/philiprehberger/mask.rb', line 76

def self.batch_scrub(strings, mode: :full, locale: nil)
  patterns = Configuration.instance.patterns(locale: locale)
  compiled = patterns.map { |pat| pat.merge(pattern: Regexp.new(pat[:pattern].source, pat[:pattern].options)) }
  strings.map { |s| Scrubber.call(s, patterns: compiled, mode: mode) }
end

.configure {|Configuration| ... } ⇒ Object

Configure custom patterns

Yields:



111
112
113
# File 'lib/philiprehberger/mask.rb', line 111

def self.configure(&block)
  block.call(Configuration.instance)
end

.configure_priority(detector_order) ⇒ Object

Set detector evaluation priority

Parameters:

  • detector_order (Array<Symbol>)

    detector names in desired order



85
86
87
# File 'lib/philiprehberger/mask.rb', line 85

def self.configure_priority(detector_order)
  Configuration.instance.set_priority(detector_order)
end

.detokenize(string, tokens:) ⇒ String

Reverse tokenization using a token lookup table

Parameters:

  • string (String)

    the tokenized string

  • tokens (Hash)

    token-to-original mapping

Returns:

  • (String)

    the restored string



64
65
66
67
68
# File 'lib/philiprehberger/mask.rb', line 64

def self.detokenize(string, tokens:)
  result = string.dup
  tokens.each { |token, original| result = result.gsub(token, original) }
  result
end

.reset_configuration!Object

Reset configuration to defaults



116
117
118
# File 'lib/philiprehberger/mask.rb', line 116

def self.reset_configuration!
  Configuration.reset!
end

.scrub(string, mode: :full) ⇒ String

Detect and redact PII patterns in a string

Parameters:

  • string (String)

    the input string

  • mode (Symbol) (defaults to: :full)

    masking mode (:full, :partial, :format_preserving)

Returns:

  • (String)

    the scrubbed string



18
19
20
# File 'lib/philiprehberger/mask.rb', line 18

def self.scrub(string, mode: :full)
  Scrubber.call(string, patterns: Configuration.instance.patterns, mode: mode)
end

.scrub_hash(data, keys: nil, mode: :full) ⇒ Hash, Array

Deep-walk a hash/array and redact sensitive values

Parameters:

  • data (Hash, Array)

    the input structure

  • keys (Array<Symbol, String>, nil) (defaults to: nil)

    specific keys to scrub

  • mode (Symbol) (defaults to: :full)

    masking mode (:full, :partial, :format_preserving)

Returns:

  • (Hash, Array)

    the scrubbed structure



28
29
30
31
# File 'lib/philiprehberger/mask.rb', line 28

def self.scrub_hash(data, keys: nil, mode: :full)
  config = Configuration.instance
  DeepScrubber.call(data, patterns: config.patterns, sensitive_keys: keys || config.sensitive_keys, mode: mode)
end

.scrub_hash_with_audit(data, keys: nil) ⇒ Hash

Deep-walk a hash/array and redact sensitive values with audit trail

Parameters:

  • data (Hash, Array)

    the input structure

  • keys (Array<Symbol, String>, nil) (defaults to: nil)

    specific keys to scrub

Returns:

  • (Hash)

    { result:, audit: […] }



38
39
40
41
# File 'lib/philiprehberger/mask.rb', line 38

def self.scrub_hash_with_audit(data, keys: nil)
  config = Configuration.instance
  DeepScrubber.call_with_audit(data, patterns: config.patterns, sensitive_keys: keys || config.sensitive_keys)
end

.scrub_io(io, mode: :full, locale: nil) ⇒ Array<String>

Read from IO line by line, scrub each line

Parameters:

  • io (IO, StringIO)

    readable IO object

  • mode (Symbol) (defaults to: :full)

    masking mode (:full, :partial, :format_preserving)

  • locale (Symbol, nil) (defaults to: nil)

    optional locale for locale-specific patterns

Returns:

  • (Array<String>)

    scrubbed lines



103
104
105
106
# File 'lib/philiprehberger/mask.rb', line 103

def self.scrub_io(io, mode: :full, locale: nil)
  patterns = Configuration.instance.patterns(locale: locale)
  io.each_line.map { |line| Scrubber.call(line, patterns: patterns, mode: mode) }
end

.scrub_with_audit(string) ⇒ Hash

Scrub a string and return an audit trail of what was masked

Parameters:

  • string (String)

    the input string

Returns:

  • (Hash)

    { result:, audit: [original:, masked:, position:] }



47
48
49
# File 'lib/philiprehberger/mask.rb', line 47

def self.scrub_with_audit(string)
  Scrubber.call_with_audit(string, patterns: Configuration.instance.patterns)
end

.tokenize(string) ⇒ Hash

Replace PII with reversible tokens

Parameters:

  • string (String)

    the input string

Returns:

  • (Hash)

    { masked:, tokens: {} }



55
56
57
# File 'lib/philiprehberger/mask.rb', line 55

def self.tokenize(string)
  Scrubber.call_with_tokens(string, patterns: Configuration.instance.patterns)
end