privacy: drop raw-IP PII columns and the dead wallets table

The published privacy policy states that IP addresses are retained only as a
salted one-way hash for rate limiting. That was true of the login-event path
but not of sessions.ip_address or audit_logs.ip_address, both of which stored
a raw client IP tied to user_id on every login.

Drop both columns and all writer/model code, so the schema enforces the policy
rather than relying on convention. The hashed rate-limit path (login_events,
restore_attempts) is unchanged and remains the only IP retention.

Also drops the `wallets` table, which was created in the initial schema and
never read or written: a latent user_id -> address / view_key store.

The operator forensic trail (admin_audit_logs, admin_sessions) deliberately
keeps its raw IP. Privileged-action forensics is a different threat model and
is not covered by the user-facing claim.
This commit is contained in:
jwinterm
2026-07-28 16:01:07 -04:00
parent 74884e368d
commit cf85dce89f
9 changed files with 39 additions and 93 deletions
@@ -0,0 +1,22 @@
-- Privacy hardening: drop raw-IP PII columns and a dead table.
--
-- Rationale: the published privacy policy (smirk.cash/privacy, PRIVACY.md) states
-- that IP addresses are retained ONLY as a salted one-way hash (for rate limiting,
-- via login_events / restore_attempts). These columns instead stored a RAW client
-- IP tied to user_id, contradicting that promise. Dropping them makes the schema
-- enforce the policy. The hashed rate-limit path (login_events.ip_hash) is untouched.
--
-- The operator forensic trail (admin_audit_logs, admin_sessions) is intentionally
-- left as-is: a tamper-evident record of privileged actions is a different threat
-- model from end-user data and is covered separately.
-- 1. sessions.ip_address — was written raw on every user login (extension + web).
ALTER TABLE sessions DROP COLUMN IF EXISTS ip_address;
-- 2. audit_logs.ip_address — raw-IP column on the (currently unwired) user audit
-- table. If security logging is wired up later, hash the IP like login_events.
ALTER TABLE audit_logs DROP COLUMN IF EXISTS ip_address;
-- 3. Dead `wallets` table — created in the initial schema but never read or written
-- by any code path (a latent user_id -> address / view_key PII store). Remove it.
DROP TABLE IF EXISTS wallets;