**Status:** Draft approved in conversation, written for implementation planning
**Goal**
Rebuild the `feat/auth-identity-foundation` intent on a clean branch from `main`, covering unified user identity, third-party login and binding, profile adoption, source-based signup defaults, unified payment routing and UX, admin configuration, compatibility with existing `main` data, and an opt-in OpenAI advanced scheduling switch.
## Scope
This design includes:
- Email login and registration
- Third-party login and binding for `LinuxDo`, `OIDC`, and `WeChat`
- Unified identity storage for email and third-party identities
- Pending auth sessions for callback-to-login/register/bind continuation
- User-controlled nickname/avatar adoption during first relevant third-party flow
- Profile binding management and avatar upload/delete
- Source-based initial grants for balance, concurrency, and subscriptions
- User management support for `last_login_at` and `last_active_at` sorting
- Unified payment display methods (`alipay`, `wechat`) mapped to a single active backend source each
- Alipay and WeChat UX routing rules across PC, mobile, H5, and WeChat environments
- Admin settings for auth providers, source defaults, payment sources, and OpenAI advanced scheduling
- Incremental migration and compatibility for existing email users and historical LinuxDo synthetic-email users
This design does not treat unrelated upstream merges, docs churn, or license changes from the old branch as required scope.
## Product Rules
### Auth and identity
- Existing email users remain valid and continue to log in with no manual action.
- Third-party first login behavior:
- Existing bound identity: direct login
- Missing identity: start first-login flow
- If `force_email_on_third_party_signup` is disabled, a first-login user may create an account without binding an email.
- If `force_email_on_third_party_signup` is enabled, the user must provide an email.
- If the provided and verified email already exists:
- show that the email already exists
- allow "verify and bind existing account"
- allow "change email and continue registration"
- do not allow bypassing the email requirement
- Upstream provider email verification is not trusted as a local bound email.
- WeChat login chooses channel by environment:
- in WeChat environment: `mp`
- outside WeChat: `open`
- WeChat primary identity key is `unionid`.
- If a WeChat login/bind flow cannot produce `unionid`, the flow fails and no fallback `openid` identity is created.
### Profile adoption
- During the first relevant third-party flow, the user can independently decide:
- replace current nickname or not
- replace current avatar or not
- This applies to first third-party registration and first third-party binding.
- The decision is explicit user choice, not automatic replacement.
### Source-based initial grants
- Source-specific defaults exist for `email`, `linuxdo`, `oidc`, and `wechat`.
- Each source defines:
- default balance
- default concurrency
- default subscriptions
- grant on signup
- grant on first bind
- Default behavior:
- grant on signup: enabled
- grant on first bind: disabled
- First-bind grants are optional and controlled per source.
- Grants must be idempotent.
### Avatar management
- Avatar supports:
- external URL
- image `data:` URL
-`data:` URL images are compressed to at most `100KB` before persistence.
- Avatar storage is database-backed.
- Avatar delete is supported.
### Payment UX and routing
- Frontend shows only two display methods:
-`alipay`
-`wechat`
- Users never choose between official providers and EasyPay explicitly.
- Backend allows only one active source per display method at a time.
- Alipay UX:
- PC: show QR code in page
- mobile: jump to Alipay app/payment flow
- WeChat UX:
- PC: show QR code in page
- non-WeChat H5: prefer H5 pay; if unavailable, tell the user to open in WeChat
- WeChat environment: prefer MP/JSAPI pay; if unavailable, fall back to H5 pay
- Payment success is confirmed by backend order state, webhook, and/or query, not only frontend return.
### OpenAI advanced scheduling
- OpenAI advanced scheduling is supported.
- It is disabled by default.
- Admin can enable it explicitly.
## Architecture
Keep `users` as the account owner table and move login identities, channel mappings, pending auth state, and first-bind grant idempotency into dedicated tables and services. Keep email login working while progressively introducing unified identity reads and writes.
Payment uses a similar split between user-visible display methods and backend provider sources. Frontend works only with stable display methods while backend resolves to the currently active source and capability matrix.
Compatibility is a first-class concern: migrations are additive, reads are compatibility-aware, and rollout must tolerate existing `main` data and short-lived frontend/backend version skew.
## Data Model
### `users`
Preserve existing account ownership and local-login fields. Extend or use:
-`email`
-`password_hash`
-`totp_enabled`
-`signup_source`
-`last_login_at`
-`last_active_at`
The `users` table remains the primary business subject for balance, concurrency, subscriptions, permissions, and profile.
### `auth_identities`
Represents all canonical login or bindable identities.