Skip to content

feat: add multi-profile support for family/household use - #15

Open
Kotobabi1 wants to merge 1 commit into
digisamroc:mainfrom
Kotobabi1:feature/multi-profile
Open

feat: add multi-profile support for family/household use#15
Kotobabi1 wants to merge 1 commit into
digisamroc:mainfrom
Kotobabi1:feature/multi-profile

Conversation

@Kotobabi1

Copy link
Copy Markdown

Multi-Profile Support ("Family Plan")

Summary

Add support for multiple profiles in a single config file, enabling families or households to send data removal requests for all members from one Eraser installation.

Motivation

Currently Eraser supports only a single person per config file. Families wanting to protect multiple members need to maintain separate config files and run Eraser separately for each — or use a wrapper script. This PR adds native multi-profile support while maintaining full backward compatibility with existing single-profile configs.

Changes

internal/config/config.go

  • Added Profiles []Profile field to Config struct (optional, omitempty)
  • Added GetProfiles() method: returns profiles if set, otherwise wraps the single profile in a slice
  • Added ProfileID(p Profile) helper: generates a stable "firstname-lastname" identifier for history namespacing
  • Updated Validate() to validate all profiles when multiple are configured

internal/history/history.go

  • Added ProfileID field to Record struct
  • Added profile_id column to removal_requests table (with migration for existing DBs)
  • Updated scanRecord, Add, GetLastRequestForBroker, GetRecentRequests to include profile_id
  • Added GetLastRequestForBrokerAndProfile() for per-profile broker tracking
  • Added GetStatsForProfile() for per-profile statistics

cmd/eraser/main.go

  • Updated runSend() to iterate over all profiles, with per-profile progress output and rate-limit pauses between profiles
  • Added --profile flag to send command for targeting a specific person by name
  • Updated runInit() to optionally set up multiple profiles interactively
  • Extracted promptProfile() helper to avoid code duplication

config.example.yaml

  • Added documented profiles section showing multi-profile YAML syntax
  • Added usage examples for --profile flag

Backward Compatibility

  • Existing single-profile configs work unchanged — GetProfiles() falls back to the single profile field
  • The profile_id column defaults to "" in the DB, so existing history records are preserved
  • The web UI continues to use the first profile (multi-profile web UI would be a follow-up)

Usage

# config.yaml
profiles:
  - first_name: John
    last_name: Doe
    email: john@example.com
    country: Germany
  - first_name: Jane
    last_name: Doe
    email: jane@example.com
    country: Germany

email:
  provider: smtp
  from: privacy@example.com
  smtp:
    host: smtp.gmail.com
    port: 465
    username: privacy@example.com
    password: xxxx-xxxx-xxxx-xxxx
    use_tls: true

options:
  template: gdpr
# Send for all profiles
eraser send --dry-run

# Send for a specific person
eraser send --profile "John"
eraser send --profile "john-doe"

Future Work

  • Profile switcher in the web UI dashboard
  • Per-profile filtering in status command
  • Per-profile inbox monitoring and response tracking

JustMaris added a commit to drumandbytes/eraser that referenced this pull request Aug 21, 2026
Broker data corrections (not previously applied in this fork):
- atlantic-fox-technologies: clear stale contact (upstream PR digisamroc#7)
- xactus: update to current DSR contact doria.sutton@xactus.com (upstream PR digisamroc#9)
- adadapted: clear stale billing contact (upstream issue digisamroc#12)

Security/reliability fixes found during the review:
- browser.go: tighten screenshot file/dir permissions to 0600/0700
  (screenshots can capture personal data mid-form-fill)
- job.go: fix data races on Job fields via GetStatus/finishedBefore/Pause,
  wire the previously-dead Cleanup() into an hourly ticker
- server.go: unify daily-send-limit logic with the CLI (removed leftover
  SendGrid/Resend-era hardcoded limits), tighten CSP (drop CDN script-src,
  add object-src 'none'), stop discarding AddBrokerResponse/
  UpdateBrokerResponseClassification/UpdateBrokerResponseBody errors -
  this silent failure is why the web UI's "Scan Complete!" summary could
  report matches while the Pipeline page stayed empty (upstream issue digisamroc#17,
  same root cause as the email_body column bug already fixed for issue digisamroc#3)
- main.go: same fix for the monitor --watch callback
- monitor.go: fix goroutine leak on ctx.Done() by draining idleDone
- layout.html + static/js/tailwind-jit.js: self-host Tailwind/HTMX instead
  of loading from live CDNs (the file was mislabeled tailwind.min.css but
  is actually the Tailwind JIT compiler's JS - renamed accordingly)

Dead code removed (confirmed zero-caller via deadcode + manual grep):
broker.LoadFromDir, several unused browser/chromedp wrappers, unused
inbox classifier/monitor/parser helpers, template.AvailableTemplates,
web.SessionStore.Count

New regression tests: sender_test.go (SMTP header injection, upstream
issue digisamroc#6, already fixed - test just locks it in), history_test.go
(email_body column round-trip, upstream issue digisamroc#3)

Reviewed but intentionally not applied:
- upstream PR digisamroc#8 (Andrews Wharton -> Stirista) would create a duplicate
  broker entry; andrews-wharton is already cleared/redirected and a
  correct standalone stirista entry already exists
- upstream PR digisamroc#14 (Retry Failed button), PR digisamroc#15 (multi-profile support),
  issue digisamroc#21 (multi-email/multi-sender support) are real feature requests
  but need a design decision before implementing
- issue digisamroc#16 (middle name) is already covered by the existing
  profile.name_variants config field
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant