WIP: feat(reporting): anonymize + encrypt debug reports before opt-in upload (#34) #445

Closed
JMR-dev wants to merge 1 commits from feat-34-debug-ingest into main
1 Commits
Author SHA1 Message Date
JMR-dev 700ce071ae feat(reporting): anonymize + encrypt debug reports before opt-in upload (#34)
Advances the client (app-repo) slice of the debug-report ingest pipeline: the
existing opt-in ReportUploadWorker now runs a best-effort PII anonymization pass
and seals each report with end-to-end (envelope) encryption to a maintainer
public key BEFORE it leaves the device, and fails closed if it cannot.

- ReportAnonymizer: pre-upload redaction of the free-text comment + log lines
  (emails, host:port, IPv4, JWTs, Bearer/Basic, key=value secrets). Re-scrubs the
  stack trace. Deliberately retains the user-supplied reply-to email (#159).
- ReportPayloadEncryptor / HybridReportPayloadEncryptor: AES-256-GCM content key
  wrapped with RSA-OAEP-SHA256 to a public key; JSON envelope. JCA only, no new
  dependency, no GMS -> F-Droid-safe. Public key from BuildConfig
  DEBUG_REPORT_PUBLIC_KEY (empty default); private key stays with the maintainer.
- ReportUploadWorker fails closed: uploads only when an endpoint AND a usable
  encryption key are configured; never transmits plaintext. PII-free AppLog at the
  anonymize/encrypt/upload lifecycle points.
- Does NOT put R2/S3 credentials or SigV4 signing in the app (would violate the
  F-Droid + secrets-never-in-app constraints); the app POSTs the encrypted envelope
  to the ingest Worker, which holds the R2 secrets server-side (#11/#34).
- Unit tests for anonymization, encryption round-trip, and the worker paths
  (success/retry/failure, fail-closed). docs/debug-report-privacy.md documents the
  data flow, anonymization, encryption scheme, and key custody (for #16/#20).

Closes #34
2026-07-08 10:24:52 -05:00