HVNid · public viewer identity

HVN Viewer Accounts

Step-by-step setup and acceptance testing for HVNid. Viewer accounts are completely separate from Command employee/admin access.

HVNidD1Secure cookiePassword reset
Do not confuse these account systems. Command employees authenticate through Cloudflare Access and a team_members role. HVN viewers authenticate through the public HVN account API and the hvn_users/hvn_user_sessions tables.

What v20.4 now includes

  • Register and sign in with email or username.
  • Passwords stored as salted PBKDF2-SHA256 hashes; plaintext passwords are never stored.
  • __Host-hvn_session session cookie with Secure, HttpOnly, SameSite=Lax and Path=/.
  • Profile, avatar, reminders, saved market/location and watchlist persistence in D1.
  • Password change that invalidates other sessions.
  • One-time, 30-minute password reset tokens stored only as SHA-256 hashes.
  • Logout and permanent account deletion.
  • Same-origin mutation checks and safe input/size limits.

Set it up in this exact order

1

Apply the current v20.4 schema

The same command-app/command-schema.sql now creates hvn_users, hvn_user_sessions and hvn_password_resets. Apply it to the D1 database used by staging. The schema is repeat-safe.

2

Bind D1 to the HVN Pages project

In the HVN Pages project, bind the same D1 database under the exact variable name COMMAND_DB. Redeploy the HVN project after changing the binding.

3

Deploy HVN with its Functions folder intact

The viewer endpoints are in hvn-site/functions/api/auth/, profile.js, location.js and watchlist.js. The HVN _routes.json sends /api/* through Pages Functions. Use Git integration or Wrangler; do not use dashboard drag-and-drop for a Pages Functions deployment.

4

Configure password-reset email

Add RESEND_API_KEY as a secret and HVN_RESET_FROM_EMAIL as a verified sender identity. Until both exist, password-reset requests intentionally return the same 503 response for known and unknown accounts instead of exposing whether an account exists.

RESEND_API_KEY = [Cloudflare secret] HVN_RESET_FROM_EMAIL = HVN <noreply@your-verified-domain.example>
5

Protect the public auth endpoints from abuse

Create Cloudflare rate-limiting/WAF rules for repeated requests to /api/auth/login, /api/auth/register and /api/auth/request-reset. Keep generic login/reset error messages; do not expose whether an email exists.

6

Test a real staging account

Register a disposable viewer. Sign out/in, edit profile, choose a market/location, add/remove a watchlist item, change password, and confirm every change survives a refresh and a second browser session.

7

Test password reset end to end

Request a reset email, open the actual link, create a new password, verify the link cannot be reused, and verify the old password no longer works.

8

Test deletion

Use a disposable account. Confirm a wrong password cannot delete it, a correct password does, the session cookie is cleared, and the viewer can no longer sign in.

Privacy/legal launch blocker: HVNid now processes viewer email, username, account settings, saved market/location and watchlist data. Because HVN legal links redirect to the Iridesceux Privacy Center, have counsel verify the Iridesceux privacy disclosures accurately cover these data before public account launch.

Automated test

Run node TESTS/hvn-viewer-auth-integration.mjs, or simply ./TESTS/run-all.sh. The automated suite tests registration, hashed passwords, cookie flags, duplicate identity rejection, sessions, profile/location/watchlist persistence, cross-origin rejection, password change, expiry, reset, logout and deletion.

Fail-closed protection

Protected profile pages wait for the real /api/auth/me result. If account initialization fails, they redirect to sign-in instead of showing stale local profile data. Password-reset responses stay generic for known/unknown accounts, and a reset token is destroyed if the email provider fails before delivery.