# ACTIVE ESM — Account access update

## Member login and registration

Open `/login` and enter an existing account's username or email and its password. Existing email/password accounts continue to work. New members can select **Create account** and register with their name, email and password; a username is optional. Password confirmation, show/hide controls and password-manager autocomplete are included.

Each account sees only the profiles linked to it. Changes to profiles, photos and links save to the database. The existing profile review and membership rules remain in place. No payments, subscription dates, roles or imported ownership are changed by registration or coupon redemption.

Imported accounts without passwords still need activation. In **Administration → Accounts & access**, find the member and select **Create activation link**. The member sets their own password through that private link. This does not require sending an email: administrators can copy the link and share it themselves. Email delivery and password-reset emails require the existing mail service to be connected. No messages were sent as part of this update.

## Coupon access without login

**General coupon: `activepass`**

An anonymous visitor enters only the coupon to open their own guest profile editor. No email, username, password or payment is required. Guest work is stored on the server and can be reopened in the same browser while its seven-day session remains valid. Creating an account from the guest workspace retains all its profiles and photos. Signing in to an existing account carries the guest profiles into that account. Clearing cookies or ending guest access loses the anonymous access route, so the interface offers account creation to retain access.

The general promotion does not select an existing account from an unverified email address. If the member is already signed in, it applies to their own linked profiles.

**Private coupon for an existing account**

1. Open **Administration → Accounts & access**.
2. Find the member and choose **Private access coupon**.
3. Select **Generate private coupon** and copy the displayed code.
4. Share it privately with that member. The website does not send it automatically.
5. The member enters the code under **Memberships → Free pass**, without a username or password.

The code expires after 48 hours and is usable once. It opens the account's linked profiles for 24 hours. This session permits profile and photo editing, but cannot view payment history, open Stripe, change passwords or emails, or use administration. Administrative accounts cannot receive these coupons. Generating another code invalidates earlier unused codes and coupon sessions. **Revoke coupon access** ends all coupon sessions for the selected member. Codes are stored only as hashes.

## Activate Google sign-in

Google login and registration use Google Identity Services. The server validates Google's signed ID token, intended client, issuer, expiration, nonce, verified-email claim and stable Google account ID. A challenge is tied to the initiating browser and can be consumed once. No Google access or refresh tokens are stored.

A real **Google Web Client ID** has not been provided, so Google is visibly unavailable until it is configured. Email/password and coupons already work independently.

1. In [Google Auth Platform](https://console.cloud.google.com/auth/clients), configure the app's branding, audience and data access, then create an OAuth client with application type **Web application**.
2. Add the exact website origin to **Authorized JavaScript origins**:
   `https://active-esm-client-preview.clean-crown-1426.chatgpt.site`
3. Add the final HTTPS origin too if deploying on another domain. Include the full scheme and hostname without a path. If the Google app remains in Testing, add the intended test users there; use the appropriate production audience before opening it to all members.
4. Copy the client ID ending in `.apps.googleusercontent.com`.
5. Paste it into **Administration → Website & email → Google Web Client ID**, then save. Alternatively configure the server's `GOOGLE_CLIENT_ID` environment variable, which takes precedence over the admin setting.
6. Reload `/login` or `/register` and test with a real Google account.

This integration uses the browser popup credential callback and a same-origin JSON endpoint. It does not require a Google client secret or OAuth redirect URI. Popups must be allowed. The CSP includes the Google Identity Services endpoints.

Returning Google members reopen the same account. Verified Gmail and Google Workspace identities can activate and connect the matching imported member account, keeping its existing profiles. A Google identity using another email provider must first authenticate an existing ESM account before linking it. Administrative identities must also sign in to their existing account first. This avoids granting control of an existing account from a third-party email claim alone.

In **Account settings**, Google members can set a separate password within ten minutes of a Google sign-in. Once a password exists, changing it requires the current password.

References: [Google ID token verification](https://developers.google.com/identity/gsi/web/guides/verify-google-id-token), [Google button setup](https://developers.google.com/identity/gsi/web/guides/display-button), [jose](https://github.com/panva/jose).

## Deployment and data preservation

The attached project retains the current live source, including newer directory, community, Elite and profile changes absent from the supplied older ZIP. Migration `0006_account_access.sql` adds nullable username and Google-subject fields, a guest flag, session scope/timestamp fields and a challenge table. It does not delete or rewrite existing users, profiles, memberships, payments or uploads.

Keep the existing database, uploaded files and server environment when upgrading. Node.js 24+ and a running backend are required; this is an HTML5 application with server-side accounts, not a static-only upload. `npm ci`, `npm test`, `npm start` remain the portable installation commands. Never place the whole project or private import JSON in a public static document root.

Automated verification covers registration, username/email login, profile ownership, guest-account conversion, guest-to-member draft transfer, coupon expiry/replay/revocation, billing and admin isolation, Google signature/claims/challenge checks and account linking. Real Google consent remains untested until a valid client ID is supplied. No production test accounts or synthetic profiles were added.
