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
-2
View File
@@ -56,7 +56,6 @@ use axum::{
Json, Router,
};
use chrono::Utc;
use ipnetwork::IpNetwork;
use serde::{Deserialize, Serialize};
use tracing::{info, instrument};
@@ -307,7 +306,6 @@ pub async fn website_verify(
refresh_token_hash,
platform: Platform::Web.to_string(),
device_info: Some("Web Browser".to_string()),
ip_address: Some(IpNetwork::from(ip)),
expires_at,
})
.await?;