Customer portal login previously checked a bcrypt customers.password_hash
in Postgres, while portal.performancewest.net validated against ERPNext —
two stores that drifted (the Paul Wilson lockout). Consolidate on ERPNext:
- erpnext-client: add verifyWebsiteUserPassword() — delegates the credential
check to Frappe /api/method/login (Host header = site name; 200=ok,401=bad).
- portal-auth /login: verify against ERPNext, then mint the pw_customer cookie.
- portal-auth /register: create+set the ERPNext password (authority) and upsert
a password-less customers profile row; takeover guard still honors any legacy
PG password until the column is dropped.
- portal-auth /reset-password + /forgot-password: write the new password to
ERPNext; forgot-password now also works for ERPNext-only users (creates the
PG profile row on demand).
- Legacy customers with only a PG bcrypt password reset via forgot-password.
- checkout: refresh the stale comment (customers row is now a profile, no pw).
Build + typecheck green.