Files
sub2api/docs/superpowers/plans/2026-04-20-auth-identity-payment-foundation.md
2026-04-20 14:41:12 +08:00

29 KiB
Raw Blame History

Auth Identity Payment Foundation Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Rebuild the auth identity, profile binding, payment routing, and OpenAI advanced scheduler foundation on top of a clean origin/main branch while preserving historical compatibility for existing email users, existing LinuxDo users, historical LinuxDo/WeChat/OIDC synthetic-email users, and historical WeChat openid-only records. Architecture: A unified identity foundation centered on durable provider subjects (email, linuxdo, oidc, wechat) and transactional pending-auth sessions; backend-owned payment source routing behind stable frontend methods (alipay, wxpay); compatibility-first migration/backfill before feature enablement. Tech Stack: Go, Gin, Ent, PostgreSQL, Redis, Vue 3, Pinia, TypeScript, Vitest, pnpm.


Non-Negotiable Product Rules

  • Preserve login continuity for existing email users, existing LinuxDo users, and historically migrated third-party users.
  • During migration, backfill historical LinuxDo/WeChat/OIDC synthetic-email users into explicit third-party identities before first post-upgrade login whenever deterministic recovery is possible.
  • During migration, surface historical WeChat openid-only records through explicit migration reports and remediation rules; do not silently reinterpret them as valid canonical identities.
  • Keep existing email login and add third-party login/bind for linuxdo, oidc, and wechat.
  • On first third-party login:
    • identity exists: direct login.
    • identity does not exist: start pending-auth flow.
    • local email binding is required only when system config says so.
    • upstream provider email verification never counts as local email verification.
  • When user-entered and locally verified email already exists:
    • offer bind-existing-account after local re-authentication.
    • offer change-email-and-create-new-account.
    • when email binding is mandatory, do not allow bypass without changing to another email.
  • On first third-party login or first third-party bind, provider nickname/avatar must be presented as independent replace options for the current nickname and avatar. They are not auto-applied.
  • Source-specific initial grants must support per-source defaults for balance, concurrency, and subscriptions.
  • Default grant timing: on successful new-account creation.
  • Optional grant timing: on first successful bind for the configured source.
  • Migration/backfill must never trigger first-bind or first-signup grants retroactively.
  • Avatar profile supports:
    • direct URL storage.
    • image data URL upload compressed to <=100KB before storing in DB.
    • explicit delete.
  • Admin user management must expose and sort by last_login_at and last_active_at.
  • WeChat login rules:
    • WeChat environment uses MP login.
    • non-WeChat browser uses Open/QR login.
    • canonical identity uses unionid.
    • when unionid is unavailable, fail the login/bind flow under the approved option-1 policy.
  • OIDC rules:
    • browser authorization-code flow always uses PKCE S256.
    • discovery issuer and ID token iss must match exactly.
    • userinfo.sub must match ID token sub when UserInfo is used.
    • upstream email_verified does not satisfy local email verification.
  • Payment UI rules:
    • user-facing methods stay 支付宝 and 微信支付.
    • backend decides whether each method routes to official provider instance or EasyPay.
    • at runtime, each visible method may only have one active source.
  • Alipay rules:
    • PC: in-page QR.
    • mobile browser: jump to Alipay payment.
  • WeChat Pay rules:
    • PC: in-page QR.
    • WeChat H5: MP/JSAPI first, fallback to H5 pay.
    • non-WeChat H5: H5 pay, or prompt to open in WeChat when unavailable.
  • Payment success pages are informational only; actual fulfillment depends on webhook or server-side reconciliation.
  • WeChat in-app payment requiring openid must use a dedicated server-backed payment OAuth resume flow rather than frontend-only recovery state.
  • OpenAI advanced scheduler is available but default-disabled.

Hard Technical Constraints From Audit

  • Browser-based third-party auth must use Authorization Code + PKCE S256.
  • PKCE must not be admin-configurable off for browser authorization-code providers.
  • OIDC identity primary key must be (issuer, subject), not email.
  • Email equality must never auto-link accounts.
  • Bind-existing-account must require explicit local re-authentication and TOTP verification when enabled.
  • Bind-current-user must originate from an already-authenticated local user and preserve explicit bind intent across callback completion.
  • OAuth redirect URI must be fixed server config, exact-match, and never derived from user input.
  • User-supplied redirect may only choose a normalized same-origin internal route after completion.
  • WeChat canonical identity must be unionid; openid remains channel/app-scoped support data only.
  • Every canonical identity uniqueness rule must include provider namespace (provider_key) consistently.
  • Callback completion must use backend session completion or a one-time opaque exchange code that is short-lived, one-time, browser-session-bound, POST-redeemed, and unusable as a bearer token.
  • Every payment order must snapshot the selected provider instance plus the order-time verification inputs required for callback verification, reconciliation, refund, and audit.
  • Frontend must not receive first-party bearer tokens through callback URL fragments in the rebuilt flow.
  • Public payment result polling must not expose order data by raw out_trade_no alone; use authenticated lookup or signed opaque result token.
  • WeChat Pay webhook handling must verify signature, decrypt payload, and compare appid, mchid, out_trade_no, amount, currency, and provider trade state against the order snapshot before fulfillment.

Baseline Notes

  • Current clean branch head when this plan was written: 721d7ab3.
  • Baseline backend verification on clean origin/main: cd backend && go test ./... passes.
  • Baseline frontend verification on clean origin/main: cd frontend && pnpm test:run currently fails in unrelated existing suites. New work must add targeted tests and avoid claiming full frontend green until those baseline failures are addressed separately.
  • Existing migration directory currently ends at 107_*; this rebuild reserves 108 through 111.

Target File Map

New backend migrations

  • backend/migrations/108_auth_identity_foundation_core.sql
  • backend/migrations/109_auth_identity_compat_backfill.sql
  • backend/migrations/110_pending_auth_and_provider_default_grants.sql
  • backend/migrations/111_payment_routing_and_scheduler_flags.sql

New or rebuilt Ent schema

  • backend/ent/schema/auth_identity.go
  • backend/ent/schema/auth_identity_channel.go
  • backend/ent/schema/pending_auth_session.go
  • backend/ent/schema/identity_adoption_decision.go

New or rebuilt backend repositories/services/handlers

  • backend/internal/repository/user_profile_identity_repo.go
  • backend/internal/repository/user_profile_identity_repo_contract_test.go
  • backend/internal/repository/auth_identity_migration_report.go
  • backend/internal/service/auth_identity_flow.go
  • backend/internal/service/auth_identity_flow_test.go
  • backend/internal/service/auth_pending_identity_service.go
  • backend/internal/service/auth_pending_identity_service_test.go
  • backend/internal/service/payment_config_service.go
  • backend/internal/service/payment_order.go
  • backend/internal/service/payment_order_lifecycle.go
  • backend/internal/service/payment_fulfillment.go
  • backend/internal/service/payment_resume_service.go
  • backend/internal/service/payment_resume_service_test.go
  • backend/internal/service/openai_account_scheduler.go
  • backend/internal/handler/auth_pending_identity_flow.go
  • backend/internal/handler/auth_linuxdo_oauth.go
  • backend/internal/handler/auth_oidc_oauth.go
  • backend/internal/handler/auth_wechat_oauth.go
  • backend/internal/handler/auth_handler.go
  • backend/internal/handler/user_handler.go
  • backend/internal/handler/payment_handler.go
  • backend/internal/handler/payment_webhook_handler.go
  • backend/internal/handler/admin/user_handler.go
  • backend/internal/handler/admin/setting_handler.go

New or rebuilt frontend API/store/views/components

  • frontend/src/api/auth.ts
  • frontend/src/api/user.ts
  • frontend/src/api/payment.ts
  • frontend/src/api/admin/settings.ts
  • frontend/src/api/admin/users.ts
  • frontend/src/stores/auth.ts
  • frontend/src/stores/payment.ts
  • frontend/src/components/auth/ThirdPartyAuthCallbackFlow.vue
  • frontend/src/components/auth/LinuxDoOAuthSection.vue
  • frontend/src/components/auth/OidcOAuthSection.vue
  • frontend/src/components/auth/WechatOAuthSection.vue
  • frontend/src/components/user/profile/ProfileAccountBindingsCard.vue
  • frontend/src/components/user/profile/ProfileInfoCard.vue
  • frontend/src/views/auth/LinuxDoCallbackView.vue
  • frontend/src/views/auth/OidcCallbackView.vue
  • frontend/src/views/auth/WechatCallbackView.vue
  • frontend/src/views/user/ProfileView.vue
  • frontend/src/views/user/PaymentView.vue
  • frontend/src/views/user/PaymentQRCodeView.vue
  • frontend/src/views/user/PaymentResultView.vue

Phase 1: Migration And Compatibility Foundation

Task 1. Create core identity schema migration

  • Implement backend/migrations/108_auth_identity_foundation_core.sql with:
    • auth_identities
    • auth_identity_channels
    • pending_auth_sessions
    • identity_adoption_decisions
    • users.last_login_at
    • users.last_active_at
    • grant-tracking columns/tables required to prevent double-award
  • Add uniqueness/index rules:
    • one canonical identity per (provider, provider_key, provider_subject)
    • one channel record per (provider, provider_channel, provider_app_id, provider_channel_subject)
    • one adoption decision per pending session
  • Model pending_auth_sessions so immutable upstream claims and mutable local flow state are stored separately; do not reintroduce a mixed metadata catch-all.
  • Preserve null-safe compatibility defaults so historical rows remain readable before backfill finishes.
  • Add explicit rollback blocks only where safe; never repeat the destructive pattern observed in old 112_update_pending_auth_sessions.sql.

Task 2. Materialize historical identities before runtime

  • Implement backend/migrations/109_auth_identity_compat_backfill.sql to backfill:
    • existing email users into auth_identities(provider=email, provider_subject=normalized_email)
    • historical LinuxDo users into auth_identities(provider=linuxdo, provider_subject=linuxdo_subject)
    • historical synthetic-email LinuxDo users into explicit LinuxDo identity rows by parsing legacy email mode and legacy provider metadata
    • historical synthetic-email WeChat users into explicit WeChat identities where unionid or equivalent deterministic provider identity is recoverable
    • historical synthetic-email OIDC users into explicit OIDC identities where deterministic provider identity is recoverable
    • profile/channel rows from historical user_external_identities-style data when present in upgraded databases
  • Write migration report output in backend/internal/repository/auth_identity_migration_report.go so production can inspect unmatched rows, openid-only WeChat rows, and non-deterministic synthetic-email rows instead of silently skipping them.
  • Set signup_source and provider provenance when recoverable from historical data. Do not flatten everything to email.

Task 3. Provider default grant and scheduler config migration

  • Implement backend/migrations/110_pending_auth_and_provider_default_grants.sql for:
    • provider-specific initial balance/concurrency/subscription defaults
    • grant timing flags: on_signup, optional on_first_bind
    • email-required-on-third-party-signup flags
    • profile avatar storage columns/settings
  • Implement backend/migrations/111_payment_routing_and_scheduler_flags.sql for:
    • stable payment method to provider-instance routing
    • visible-method normalization from historical supported_types, payment_mode, and legacy aliases such as wxpay_direct
    • admin exclusivity flags for alipay and wxpay
    • advanced scheduler enable flag defaulting to disabled

Task 4. Generate Ent and compile migration-safe model layer

  • Add the schema definitions in:
    • backend/ent/schema/auth_identity.go
    • backend/ent/schema/auth_identity_channel.go
    • backend/ent/schema/pending_auth_session.go
    • backend/ent/schema/identity_adoption_decision.go
  • Run:
    cd backend
    go generate ./ent
    
  • Compile after generation:
    cd backend
    go test ./... -run '^$'
    
  • Commit checkpoint:
    git add backend/migrations backend/ent/schema backend/ent
    git commit -m "feat: add auth identity foundation schema"
    

Phase 2: Backend Identity Flow Rebuild

Task 5. Build a single repository contract for identity lookups and grants

  • Implement backend/internal/repository/user_profile_identity_repo.go with transactional helpers for:
    • get user by canonical identity
    • get user by channel identity
    • create canonical + channel identity together
    • bind identity to existing user after verified re-auth
    • record one-time provider grant award
    • record adoption preference decisions
    • update last_login_at and last_active_at
  • Add repository contract coverage in backend/internal/repository/user_profile_identity_repo_contract_test.go.
  • Enforce dual-write for email registration/login so users.email and auth_identities(provider=email, ...) stay consistent from this phase onward.
  • Add repository coverage proving last_login_at and last_active_at use the required field names and are not silently replaced by derived last_used_at logic.

Task 6. Rebuild transactional pending-auth service

  • Implement backend/internal/service/auth_pending_identity_service.go and tests to own these flows:
    • create pending session from third-party callback
    • verify local email code
    • create new account from pending session with correct signup_source
    • bind pending identity to existing account after password/TOTP re-auth
    • apply configured provider defaults on the correct trigger only once
    • store provider nickname/avatar candidates and user opt-in replacement decisions independently
  • Implement callback completion so pending auth can finish through backend session completion or a one-time exchange code:
    • short TTL
    • one-time use
    • browser-session binding
    • POST redemption only
    • safe mixed-version bridge to legacy pending-token aliases during rollout
  • Keep pending session payload normalized:
    • provider identity fields live in typed columns/JSON structure
    • mutable local progression lives separately from immutable upstream claims
    • avoid the old branchs mixed metadata and upstream_identity_payload ambiguity
  • Do not call plain email registration helpers from this flow. The old feature branch bug where pending third-party signup fell back to RegisterWithVerification must not reappear.

Task 7. Rebuild provider callback adapters

  • Refactor these handlers to thin adapters over the shared pending-auth service:
    • backend/internal/handler/auth_linuxdo_oauth.go
    • backend/internal/handler/auth_oidc_oauth.go
    • backend/internal/handler/auth_wechat_oauth.go
  • For OIDC:
    • require PKCE S256, state, and nonce
    • validate discovery issuer, iss, aud, optional azp, exp, and nonce
    • verify userinfo.sub == id_token.sub when UserInfo is used
    • persist canonical identity as (issuer, sub)
  • For WeChat:
    • MP flow in WeChat UA
    • Open/QR flow outside WeChat UA
    • website login uses authorization-code flow and persists channel/app binding
    • persist channel identity by (channel, appid, openid)
    • persist canonical identity by unionid
    • hard-fail when unionid is absent under the approved product policy
  • Replace callback URL fragment token delivery with backend session completion or one-time exchange code consumed by frontend/src/stores/auth.ts.

Task 8. Rebuild auth endpoints and profile binding endpoints

  • Implement backend/internal/handler/auth_pending_identity_flow.go for:
    • fetch pending session summary
    • submit verified email
    • choose create-new-account or bind-existing-account
    • submit nickname/avatar replacement choices
  • Make bind-existing-account and bind-current-user flows explicit:
    • no automatic linking on matching email
    • fresh password/TOTP proof is scoped to the intended target account only
    • no automatic metadata merge beyond explicitly selected nickname/avatar adoption
  • Update backend/internal/handler/auth_handler.go and backend/internal/handler/user_handler.go to expose:
    • current bindings summary
    • start-bind endpoints for LinuxDo/OIDC/WeChat
    • disconnect endpoints with safety checks
    • avatar upload/delete endpoints
  • Avatar handling requirements:
    • allow external URL
    • allow data URL upload
    • compress image payload to <=100KB
    • store compressed value in DB
    • deleting custom avatar must not implicitly resurrect stale provider avatar unless the user explicitly chooses provider avatar again

Task 9. Add admin visibility and sorting

  • Update backend/internal/handler/admin/user_handler.go and supporting query/service code so admin list supports:
    • last_login_at
    • last_active_at
    • sorting by both
    • binding/provider summary columns
  • Update backend/internal/handler/admin/setting_handler.go and setting service code for:
    • provider initial grant config
    • mandatory-email-on-third-party-signup config
    • payment source exclusivity config
    • advanced scheduler toggle

Task 10. Backend verification checkpoint

  • Run targeted backend tests:
    cd backend
    go test ./internal/repository -run 'TestUserProfileIdentity|TestAuthIdentityMigration'
    go test ./internal/service -run 'TestAuthIdentityFlow|TestPendingAuthIdentity|TestOpenAIAccountScheduler'
    go test ./internal/handler -run 'TestLinuxDo|TestOidc|TestWechat|TestPaymentWebhook'
    go test ./...
    
  • Commit checkpoint:
    git add backend
    git commit -m "feat: rebuild auth identity backend flows"
    

Phase 3: Frontend Third-Party Flow And Profile UX

Task 11. Rebuild callback flow UI around pending session decisions

  • Rebuild frontend/src/components/auth/ThirdPartyAuthCallbackFlow.vue so it:
    • loads pending-session summary from backend
    • shows provider nickname/avatar candidates
    • lets user independently choose nickname replacement and avatar replacement
    • handles create-new-account vs bind-existing-account
    • enforces verified local email before completion when required
    • handles “email already exists” by branching to bind-existing-account or change-email-and-create-new-account
  • Update:
    • frontend/src/views/auth/LinuxDoCallbackView.vue
    • frontend/src/views/auth/OidcCallbackView.vue
    • frontend/src/views/auth/WechatCallbackView.vue
    • frontend/src/api/auth.ts
    • frontend/src/stores/auth.ts
  • Replace any token-fragment bootstrap with backend session completion or one-time exchange code flow.
  • During rollout, keep temporary compatibility readers for legacy pending-token aliases behind a bounded bridge contract and explicit removal step.

Task 12. Rebuild profile account binding and avatar UX

  • Rebuild frontend/src/components/user/profile/ProfileAccountBindingsCard.vue to:
    • show linked LinuxDo/OIDC/WeChat providers
    • start bind/unbind flows
    • show provider avatars and nicknames as reference only
    • prevent unsafe disconnect when it would strand the account
  • Rebuild frontend/src/components/user/profile/ProfileInfoCard.vue and frontend/src/views/user/ProfileView.vue to:
    • support avatar URL entry
    • support data URL upload/compression preview
    • support avatar delete
    • clearly separate current profile nickname/avatar from provider-sourced suggested nickname/avatar

Task 13. Add frontend tests for rebuilt auth/profile flows

  • Add or update:
    • frontend/src/components/auth/__tests__/ThirdPartyAuthCallbackFlow.spec.ts
    • frontend/src/components/auth/__tests__/LinuxDoCallbackView.spec.ts
    • frontend/src/components/auth/__tests__/WechatCallbackView.spec.ts
    • frontend/src/components/user/profile/__tests__/ProfileAccountBindingsCard.spec.ts
    • frontend/src/components/user/profile/__tests__/ProfileInfoCard.spec.ts
  • Cover:
    • email-required branch
    • email-conflict branch
    • bind-existing-account with re-auth prompt
    • nickname replacement only
    • avatar replacement only
    • neither replacement
    • avatar delete after prior provider adoption

Phase 4: Payment Routing Rebuild

Task 14. Normalize payment routing backend

  • Rebuild backend/internal/service/payment_config_service.go to expose a stable method-routing contract:
    • frontend visible methods remain alipay and wxpay
    • admin chooses which provider instance serves each method
    • runtime validation guarantees only one active source per visible method
  • Add migration logic and tests to normalize historical provider-instance config:
    • supported_types
    • payment_mode
    • legacy aliases such as wxpay_direct
    • historical limit config
  • Rebuild backend/internal/service/payment_order.go and backend/internal/service/payment_order_lifecycle.go so order creation snapshots:
    • visible method
    • selected provider instance id
    • provider type
    • provider capability mode
    • verification-critical provider fields needed for later callback/query/refund validation
  • Rebuild backend/internal/handler/payment_handler.go for UX rules:
    • Alipay PC: QR page
    • Alipay mobile: direct jump
    • WeChat PC: QR page
    • WeChat H5 in WeChat: MP/JSAPI first, fallback to H5
    • WeChat H5 outside WeChat: H5 or “open in WeChat” prompt when unavailable
  • Never derive canonical return URL from Referer; use configured or signed internal callback targets only.
  • Implement backend/internal/service/payment_resume_service.go so WeChat in-app payment OAuth resume is server-backed rather than localStorage-backed:
    • create oauth_required resume context
    • persist amount/order_type/plan_id/visible method/redirect/state
    • redeem callback into same-origin internal resume target
    • expire and consume resume context safely

Task 15. Make fulfillment and reconciliation provider-instance-safe

  • Rebuild backend/internal/handler/payment_webhook_handler.go and backend/internal/service/payment_fulfillment.go so:
    • verification uses the orders original provider instance
    • webhook processing is idempotent by provider event id and internal order id
    • missed webhook recovery uses server-side provider query, not frontend success return
  • For WeChat Pay specifically, enforce:
    • fixed HTTPS notify_url with no query params
    • no dependency on user login state
    • signature verification before decrypt
    • APIv3 decrypt before business parsing
    • comparison of appid, mchid, out_trade_no, amount, currency, and trade state against the order snapshot
  • Harden frontend/src/views/user/PaymentResultView.vue and frontend/src/api/payment.ts so result polling uses an authenticated order lookup or signed opaque token, not a raw public out_trade_no query.

Task 16. Rebuild payment frontend views

  • Rebuild frontend/src/views/user/PaymentView.vue, frontend/src/views/user/PaymentQRCodeView.vue, and frontend/src/stores/payment.ts so:
    • only two buttons are shown to user: 支付宝 and 微信支付
    • frontend does not leak official-vs-EasyPay distinction
    • route-specific copy handles QR, jump, MP, H5 fallback correctly
  • Rebuild WeChat in-app payment resume UX around the server-backed resume context:
    • handle oauth_required
    • continue from same-origin resume target
    • avoid long-lived localStorage as the source of truth
  • Add or update:
    • frontend/src/views/user/__tests__/PaymentView.spec.ts
    • frontend/src/views/user/__tests__/PaymentResultView.spec.ts
    • backend webhook/payment routing tests

Task 17. Payment verification checkpoint

  • Run:
    cd backend
    go test ./internal/service -run 'TestPayment'
    go test ./internal/handler -run 'TestPayment'
    cd ../frontend
    pnpm test:run src/views/user/__tests__/PaymentView.spec.ts src/views/user/__tests__/PaymentResultView.spec.ts
    
  • Commit checkpoint:
    git add backend frontend
    git commit -m "feat: rebuild payment routing foundation"
    

Phase 5: Scheduler, Rollout, And Final Compatibility Pass

Task 18. Gate advanced scheduler behind explicit config

  • Update backend/internal/service/openai_account_scheduler.go and related admin setting surfaces so:
    • advanced scheduler remains compiled and testable
    • default runtime state is disabled
    • enablement is explicit through admin settings
    • legacy scheduling behavior remains default on upgrade
  • Add targeted coverage in backend/internal/service/openai_account_scheduler_test.go.

Task 19. Complete compatibility and rollout safety checks

  • Add migration/repository tests covering:
    • historical email-only user login after upgrade
    • historical LinuxDo user login after upgrade
    • historical synthetic-email LinuxDo user login after upgrade
    • historical synthetic-email WeChat user login after upgrade
    • historical synthetic-email OIDC user login after upgrade
    • historical WeChat openid-only rows are reported or explicitly remediated
    • no retroactive grant replay during migration
    • first-bind grant fires once only when enabled
    • email identity dual-write stays consistent
    • bind-existing-account requires password and TOTP where configured
    • mixed-version callback token bridge works during rollout and is removable afterward
    • historical payment config is normalized into visible-method routing without refund/query regression
  • Add deploy sequencing note to release docs or internal runbook:
    1. deploy schema and backfill release.
    2. inspect migration report for unmatched rows.
    3. deploy backend identity/payment compatibility code with exchange bridge and legacy token aliases still enabled.
    4. deploy frontend callback/profile/payment UI using session completion, exchange code, and server-backed WeChat payment resume.
    5. remove legacy callback/token parsing after mixed-version window closes.
    6. enable strict email-required signup or provider bind grants only after metrics are healthy.

Task 20. Final verification and handoff

  • Run final backend verification:
    cd backend
    go test ./...
    
  • Run targeted frontend verification:
    cd frontend
    pnpm test:run \
      src/components/auth/__tests__/ThirdPartyAuthCallbackFlow.spec.ts \
      src/components/auth/__tests__/LinuxDoCallbackView.spec.ts \
      src/components/auth/__tests__/WechatCallbackView.spec.ts \
      src/components/user/profile/__tests__/ProfileAccountBindingsCard.spec.ts \
      src/components/user/profile/__tests__/ProfileInfoCard.spec.ts \
      src/views/user/__tests__/PaymentView.spec.ts \
      src/views/user/__tests__/PaymentResultView.spec.ts
    
  • Run focused manual smoke checks:
    • email login with existing account
    • LinuxDo existing-account login after migration
    • WeChat synthetic-email account login after migration
    • OIDC synthetic-email account login after migration
    • third-party first login create-new-account path
    • third-party first login bind-existing-account path
    • first third-party bind with optional nickname/avatar replacement
    • PC Alipay QR
    • mobile Alipay jump
    • PC WeChat QR
    • WeChat H5 MP/JSAPI path
    • WeChat in-app OAuth resume path
    • non-WeChat H5 fallback path
  • Commit final checkpoint:
    git add docs backend frontend
    git commit -m "feat: rebuild auth identity and payment foundation"
    

Review Checklist

  • No flow still relies on provider email equality for account linking.
  • No flow still creates third-party users through plain email registration helpers.
  • No callback still returns first-party bearer tokens in URL fragments.
  • No callback completion path can be replayed as a bearer token substitute.
  • No payment result view trusts provider return page as authoritative fulfillment.
  • No webhook verification path selects provider credentials from “currently active config” instead of the order snapshot.
  • Existing email users, historical LinuxDo/WeChat/OIDC users, and openid-only WeChat remediation cases are covered by migration tests.
  • Avatar adoption and deletion semantics are explicit and reversible.
  • Grant timing is source-aware and one-time only.