* docs: PR2 GDPR IP/privacy audit design spec
Second of five GDPR PRs (#6701). Audit identifies four log-sites that
leak IPs despite disableIPlogging=true, proposes a tri-state ipLogging
setting with a back-compat shim, and specifies a doc/privacy.md that
documents Etherpad's actual IP handling.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs: PR2 GDPR IP/privacy audit implementation plan
7 TDD-structured tasks: anonymizeIp helper + unit tests, tri-state
ipLogging setting with disableIPlogging deprecation shim, wiring
through 5 leaking log sites, clientVars.clientIp removal, access-log
integration test, doc/privacy.md, and PR handoff.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(gdpr): anonymizeIp helper with v4/v6/v4-mapped truncation
* feat(gdpr): tri-state ipLogging setting + disableIPlogging shim
* fix(gdpr): route every IP log site through anonymizeIp
Closes four leaks where disableIPlogging was silently ignored
(rate-limit warn, both auth-log calls in webaccess, import/export
rate-limit warn) and normalises the four that did honour the flag
onto the new ipLogging tri-state via the shared helper.
* chore(gdpr): drop dead clientVars.clientIp placeholder
Server side: remove the literal '127.0.0.1' assignments from both
clientVars and collab_client_vars. Type side: drop clientIp from
ClientVarPayload and ServerVar. pad.getClientIp now returns the same
'127.0.0.1' literal as a plugin-compat shim (pad_utils.uniqueId still
uses it as a prefix).
* test(gdpr): ipLogging modes + disableIPlogging shim
* docs(gdpr): operator-facing privacy and IP handling statement
* fix(gdpr): validate ipLogging at load + regression test for log sites
Qodo review:
- settings.ipLogging is loaded as a trusted union but nothing enforced
the shape. An unknown value (e.g. a typo or null) silently fell
through to anonymizeIp's "truncated" branch and emitted partially
redacted IPs. Fall back to "anonymous" with a WARN at load time.
- New regression test scans the four known log-sites for raw
req.ip / socket.request.ip / request.ip inside logger calls that
don't wrap through anonymizeIp / logIp, so a future edit that
re-introduces a raw IP fails CI.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>