SFTP user passwords were stored as plaintext in the JSON user store.
This replaces plaintext storage with bcrypt hashing:
- Add HashedPassword field to User struct for bcrypt hashes
- SetPassword() now hashes with bcrypt.DefaultCost
- CheckPassword() verifies against bcrypt hash with transparent
legacy migration: plaintext passwords auto-upgrade on successful login
- CreateUser() uses SetPassword() instead of direct assignment
- ValidatePassword() delegates to CheckPassword() and persists
migrated hashes
Existing users with plaintext passwords are transparently migrated
to bcrypt on their next successful authentication.