Class: Privacy::ScrubService

Inherits:
Object
  • Object
show all
Defined in:
app/services/privacy/scrub_service.rb

Overview

Runs the automated Tier 1 + Tier 2 anonymization sequence from
doc/operations/PRIVACY_REQUESTS_RUNBOOK.md §6 against a Party (and its
Account, when present). Reusable across the Facebook callback path
(Privacy::DataDeletionWorker) and manual-request paths (admin button
in /admin/privacy/deletion_requests/:id).

What this service does NOT do — by design:

  • Processor-side payment detach (Stripe/PayPal) — delegated to
    ProcessorDetachWorker so a flaky outbound HTTP call cannot
    roll back the local-data anonymization
  • Tier-3 risk evaluation — that lives in ManualReviewDetector
    and runs before this service is invoked

Tiers (full taxonomy in the runbook):

  • Tier 1: identity fields → aggressive anonymization. Account + Auth
    destroyed; Party PII fields blanked; visits scrubbed; consent reset.
  • Tier 2: transaction-snapshot PII → anonymize but keep row + linkage
    (Payment cardholder names, Address shipping/billing snapshots) so
    financial records remain auditable per IRS recordkeeping.

Examples:

result = Privacy::ScrubService.call(party: customer)
result.scrubbed?   # => true
result.summary     # => { account_destroyed: true, authentications_destroyed: 1, ... }

Defined Under Namespace

Classes: Result

Constant Summary collapse

REDACTED_NAME =

Placeholder values shared across the codebase so a partial scrub is
detectable later (e.g. find_each on full_name ILIKE 'REDACTED-%').

'REDACTED'
REDACTED_CITY =
'REDACTED'
REDACTED_ZIP =
'00000'
REDACTED_DOMAIN =
'privacy.warmlyyours.com'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(party:) ⇒ ScrubService

Returns a new instance of ScrubService.



44
45
46
47
# File 'app/services/privacy/scrub_service.rb', line 44

def initialize(party:)
  @party = party
  @summary = {}
end

Class Method Details

.call(party:) ⇒ Object



40
41
42
# File 'app/services/privacy/scrub_service.rb', line 40

def self.call(party:)
  new(party: party).call
end

Instance Method Details

#callObject



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'app/services/privacy/scrub_service.rb', line 49

def call
  ActiveRecord::Base.transaction do
    scrub_tier_1!
    scrub_tier_2!
    destroy_account!
    purge_paper_trail!
  end

  Result.new(scrubbed?: true, summary: @summary, error: nil)
rescue StandardError => e
  Rails.logger.error "Privacy::ScrubService failed for party=#{@party&.id}: #{e.class}: #{e.message}"
  Result.new(scrubbed?: false, summary: @summary, error: "#{e.class}: #{e.message}")
end