# Plan 07.1-01 Summary — Session revocation on privilege change (backend)

**Status:** Complete  
**Wave:** 1

## What was done

### services/auth.py
- Extended `revoke_all_refresh_tokens` signature: added `skip_token_hash: Optional[str] = None`
- When `skip_token_hash` is set, the WHERE clause excludes that token (`RefreshToken.token_hash != skip_token_hash`), so the calling session stays alive
- Backwards-compatible: all existing callers that pass no third argument behave identically

### api/auth.py
- `change_password`: derives skip hash from refresh cookie → calls `revoke_all_refresh_tokens` with skip → extends audit log `metadata_` with `sessions_revoked` → returns `{"message": "Password updated", "sessions_revoked": revoked}`
- `enable_totp`: same pattern → returns `{"backup_codes": plain_codes, "sessions_revoked": revoked}`
- `disable_totp`: same pattern → returns `{"message": "TOTP disabled", "sessions_revoked": revoked}`
- `logout_all` handler: unchanged (intentionally revokes all sessions without skip)

## Verification

```
grep -c "skip_token_hash" services/auth.py   → 4
grep -c "sessions_revoked" api/auth.py       → 7
grep -c "skip_token_hash" api/auth.py        → 6
python3 -c "import api.auth; import services.auth" → exits 0
```
