soulsync/database
BoulderBadgeDad 8e1b678d6f Native login (increment 1/3): per-profile password DB layer
Opt-in username/password login — profiles become real accounts. This is the data
layer: a per-profile login password, kept SEPARATE from the quick-switch PIN
(different security purpose; a 4-digit PIN must not become the password guarding a
public instance).

- Additive migration: profiles.password_hash column (idempotent, metadata-flagged).
- set_profile_password / verify_profile_password / profile_has_password /
  get_profile_by_name (the login username = profile name, unique + case-insensitive).
- Security default: a profile with NO password is NOT loginable (verify returns
  False) — unlike the PIN where "no PIN = always valid". You can't authenticate to
  an account with no credential.

Tests: migration adds the column; set/verify; no-password-never-loginable; clearing;
name lookup; and password is fully independent of the PIN. 6 tests pass. Next:
the login endpoint + require_login gate (increment 2).
2026-06-10 21:57:44 -07:00
..
__init__.py basic db structure 2025-08-05 22:43:04 -07:00
music_database.py Native login (increment 1/3): per-profile password DB layer 2026-06-10 21:57:44 -07:00
personalized_schema.py Personalized pipeline: auto-refresh stale snapshots after watchlist scan 2026-05-15 20:53:03 -07:00