Module: Legion::Phi
- Defined in:
- lib/legion/phi.rb,
lib/legion/phi/erasure.rb,
lib/legion/phi/access_log.rb
Defined Under Namespace
Constant Summary collapse
- PHI_TAG =
:phi- DEFAULT_PHI_PATTERNS =
%w[ ssn social_security mrn medical_record dob date_of_birth patient_name first_name last_name full_name phone phone_number email address zip zipcode postal_code diagnosis icd_code npi insurance_id member_id account_number credit_card passport drivers_license ip_address device_id ].freeze
Class Method Summary collapse
-
.auto_detect_fields(data) ⇒ Object
Auto-detect PHI fields by matching field names against configurable patterns.
- .compiled_defaults ⇒ Object
-
.erase(data, key_id:) ⇒ Object
Cryptographic erasure: re-encrypt PHI fields with a throwaway key, then destroy the key.
-
.phi_fields(data) ⇒ Object
Returns the list of PHI-tagged field names.
-
.phi_patterns ⇒ Object
Returns the configured PHI field patterns (regex strings).
-
.redact(data) ⇒ Object
Returns a copy of data with all PHI fields replaced with [REDACTED].
- .settings_patterns ⇒ Object
-
.tag(data, fields:) ⇒ Object
Marks specific hash fields as containing PHI by adding __phi_fields metadata.
-
.tagged?(data) ⇒ Boolean
Returns true if the hash has a PHI tag.
Class Method Details
.auto_detect_fields(data) ⇒ Object
Auto-detect PHI fields by matching field names against configurable patterns.
95 96 97 98 99 100 101 102 103 |
# File 'lib/legion/phi.rb', line 95 def auto_detect_fields(data) return [] unless data.is_a?(Hash) patterns = phi_patterns data.keys.select do |key| key_str = key.to_s.downcase patterns.any? { |pat| key_str.match?(pat) } end end |
.compiled_defaults ⇒ Object
116 117 118 |
# File 'lib/legion/phi.rb', line 116 def compiled_defaults DEFAULT_PHI_PATTERNS.map { |p| Regexp.new("\\b#{Regexp.escape(p)}\\b", Regexp::IGNORECASE) } end |
.erase(data, key_id:) ⇒ Object
Cryptographic erasure: re-encrypt PHI fields with a throwaway key, then destroy the key. Returns the erased record (PHI fields replaced with erasure markers).
85 86 87 88 89 90 91 92 |
# File 'lib/legion/phi.rb', line 85 def erase(data, key_id:) return data unless data.is_a?(Hash) fields = phi_fields(data) + auto_detect_fields(data) fields = fields.uniq Erasure.erase_record(record: data, phi_fields: fields, key_id: key_id) end |
.phi_fields(data) ⇒ Object
Returns the list of PHI-tagged field names.
63 64 65 66 67 |
# File 'lib/legion/phi.rb', line 63 def phi_fields(data) return [] unless tagged?(data) data[:__phi_fields] || [] end |
.phi_patterns ⇒ Object
Returns the configured PHI field patterns (regex strings).
106 107 108 109 110 111 112 113 114 |
# File 'lib/legion/phi.rb', line 106 def phi_patterns configured = settings_patterns return compiled_defaults if configured.nil? || configured.empty? configured.map { |p| Regexp.new(p, Regexp::IGNORECASE) } rescue StandardError => e Legion::Logging.warn "Phi#phi_patterns failed to compile configured patterns: #{e.}" if defined?(Legion::Logging) compiled_defaults end |
.redact(data) ⇒ Object
Returns a copy of data with all PHI fields replaced with [REDACTED].
70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/legion/phi.rb', line 70 def redact(data) return data unless data.is_a?(Hash) fields = phi_fields(data) + auto_detect_fields(data) fields = fields.uniq result = data.dup fields.each do |field| result[field] = '[REDACTED]' if result.key?(field) end result end |
.settings_patterns ⇒ Object
120 121 122 123 124 125 126 127 |
# File 'lib/legion/phi.rb', line 120 def settings_patterns return nil unless defined?(Legion::Settings) Legion::Settings.dig(:phi, :field_patterns) rescue StandardError => e Legion::Logging.debug "Phi#settings_patterns failed: #{e.}" if defined?(Legion::Logging) nil end |
.tag(data, fields:) ⇒ Object
Marks specific hash fields as containing PHI by adding __phi_fields metadata.
45 46 47 48 49 50 51 52 53 |
# File 'lib/legion/phi.rb', line 45 def tag(data, fields:) raise ArgumentError, 'data must be a Hash' unless data.is_a?(Hash) raise ArgumentError, 'fields must be an Array' unless fields.is_a?(Array) result = data.dup existing = result[:__phi_fields] || [] result[:__phi_fields] = (existing + fields.map(&:to_sym)).uniq result end |
.tagged?(data) ⇒ Boolean
Returns true if the hash has a PHI tag.
56 57 58 59 60 |
# File 'lib/legion/phi.rb', line 56 def tagged?(data) return false unless data.is_a?(Hash) data.key?(:__phi_fields) && !data[:__phi_fields].nil? end |