Skip to content

feat(auth): add independent email-code sign-in across clients and markets - #3042

Merged
bobleer merged 24 commits into
GCWing:mainfrom
bobleer:bob/email-code-login
Sep 15, 2026
Merged

bobleer merged 24 commits into
GCWing:mainfrom
bobleer:bob/email-code-login

Conversation

@bobleer

@bobleer bobleer commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Add email verification-code sign-in as an independent alternative to GitHub across desktop, CLI, mobile web, native mobile, and both markets. Email accounts do not use passwords and are never automatically linked to GitHub accounts.

This includes the implementation and follow-up fixes: authentication and migrations, client integration, deployment build fixes, branded email delivery, account display/avatar corrections, sign-in popup handling, and the mobile empty-device experience.

Type and Areas

Type: Feature, bug fix, UI/UX, tests, deployment documentation.

Areas: Identity service, Relay, MiniApp/Skin markets, desktop/Web UI, CLI, mobile web, Android/iOS/HarmonyOS, brand assets.

Motivation / Impact

  • Users can choose GitHub or a one-time email code. Codes expire after ten minutes; only keyed digests are stored, with persistent rate limits and atomic consumption.
  • Older clients retain the GitHub flow; updated clients opt into the shared chooser with methods=all. Existing identity IDs and device/session ownership remain intact.
  • Verification emails have HTML and UTF-8 plain-text bodies. The original application PNG is embedded as a CID image, avoiding an external-image dependency and the blank black placeholder.
  • Desktop account controls and both market headers display the verified email for email accounts and provide an avatar fallback. Private email metadata is returned separately from public owner profiles.
  • Mobile web uses a dedicated browser sign-in popup with cancel/reopen/completion handling. The empty-device page provides setup guidance and distinguishes an empty account from a failed directory request.
  • Remove the requested market footer taglines in all three locales. Include the vendored dependency in market Docker contexts and the HarmonyOS nominal-type fixes required by the client changes.

Verification

Passed during implementation and follow-up work:

  • cargo test -p openbitfun-miniapp-market-service --lib email_ — 8 tests, including legacy migration preservation, authenticated email metadata, code consumption, and MIME structure.
  • cargo test -p openbitfun-services-integrations --no-default-features --features account-identity --lib account_identity::profile_tests — legacy payload and additive email projection.
  • pnpm --dir src/mobile-web run test:account-login
  • pnpm --dir src/mobile-web run test:account-browser — 16 account/persistence/race tests; the added cross-origin popup regression was also run separately with node --test --test-name-pattern='sign-in uses a separate popup' src/mobile-web/tests/browser-account.test.mjs.
  • pnpm --dir src/web-ui exec vitest run src/infrastructure/account-identity/AccountIdentityService.test.ts — 6 tests.
  • Type checks for Web UI, mobile web, MiniApp market, and Skin market; both market test suites (17 and 27 tests); market and mobile-web production builds.
  • node --test --test-name-pattern='verification email' scripts/generate-brand-assets.test.mjs
  • pnpm run theme:color-audit:all — all 23 surfaces; pnpm run i18n:audit — no warnings.
  • Disposable Chrome checks: 320/390/768/1200px layouts, light/dark email rendering without external images, email/absent-avatar/broken-avatar market headers, cross-origin popup cancellation and completion, empty-device errors and subsequent connection.
  • Real SMTP delivery and email-code login acceptance were completed during implementation. Production auth/market health, image revisions, and published mobile assets were verified after deployment; database/artifact backups were checked before market updates.

Known existing check failures, not hidden or relaxed here:

  • Mobile UI component audit flags raw buttons in unchanged DeviceToolsPage.tsx.
  • Broad Web UI typography audit has existing violations in unchanged files.
  • Existing iOS file-preview and brand tray source assertions are stale; focused checks for this change passed.

Additional sign-in localization verification:

  • Caller-selected language is carried from desktop, mobile web, both markets, Android, iOS, and HarmonyOS to the auth chooser. The auth page resolves aliases through the shared locale contract and retains language through completion.
  • Verification emails now have complete English, Simplified Chinese, and Traditional Chinese subjects/HTML/plain text; older clients can omit the additive locale field and receive English.
  • Auth favicons use the actual PNG bytes served by the official website.
  • Focused email-auth tests: 9 passed. MiniApp tests: 25 passed; Skin tests: 28 passed; mobile account tests: 14 passed. Android Kotlin compilation and HarmonyOS HAP build passed. iOS account-copy tests passed; the full pure-Swift script still stops at the existing remote file-preview authority assertion.
  • English completion/sign-in and localized error text were checked in the browser. i18n audit reports zero warnings; all 23 theme audit surfaces pass.

The outbound mail integration additionally supports an explicit private-IP-only SMTP relay mode, with no plaintext credential submission. Secure authenticated SMTP remains the default; 10 focused email-auth tests cover the new constraints and prior flows. Production Postfix/DKIM keys remain on the server and are not committed. The relay permits senders across the owned domain. Auth now submits to the same-host relay; direct MX delivery was accepted by Gmail, 163, QQ, and Proton, and the user confirmed receipt at all four addresses. The initial QQ SPF-cache rejection cleared on a targeted retry.

The repository now includes deploy/outbound-mail/README.md, with a corresponding instance-specific runbook on the server. Email logo, header brand, and footer brand link to the official HTTPS website in all three locales; plain-text mail includes the website URL. Focused MIME tests, browser previews, repository hygiene, i18n, and theme audits passed after this update.

Windows CI exposed a mock-model lifetime race during cold terminal startup. The mock listener now stays alive until its owning test drops it, rather than expiring 30 seconds after fixture creation. Existing terminal output/cancellation deadlines remain unchanged; the focused terminal regression passed locally (1 test); final Windows CI validates the platform-specific cold-start path.

Reviewer Notes

  • Email identity migrations preserve internal user IDs and foreign keys. Do not roll pre-email binaries over databases that already contain email users; use a forward fix.
  • Email display is additive and private to authenticated account responses; public publisher identities are unchanged. Existing desktop binaries require rebuilding to consume the new display metadata.
  • Browser popup presentation is ultimately controlled by the browser, particularly on mobile. The opener relationship is retained for trusted, allowlisted auth destinations so Chrome can close the cross-origin window.
  • Remote control was exercised through browser/Relay fixtures and the production relay/account flow. This does not claim a full physical-device matrix or new Remote Workspace, Peer Device Mode, or Detached Dispatch coverage.
  • Production deployments used committed revisions and retained existing data. No SMTP credentials, verification codes, account tokens, or local QA artifacts are included.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable.

Email sign-in review follow-up

  • New verification codes are exactly eight random digits, including leading zeroes. Only eight-digit input is accepted; six-digit codes must be requested again. Codes remain valid for ten minutes with at most five verification attempts.
  • Send limits: one message per address per rolling minute, twenty per address per rolling day, three hundred globally per rolling minute, and no global daily cap. Start/send/verify admission counters are separate.
  • Fixed a reproduced refresh race where the same refresh token could succeed twice. Refresh consumption, family revocation, and replacement issuance now commit atomically. Device-token claims also roll back if issuance fails.
  • Expired sign-in requests now stop the dead-end resend loop and explain how to restart from the originating app. Delivery failures and service throttling have distinct English, Simplified Chinese, and Traditional Chinese copy.
  • Auth responses now explicitly prohibit caching and referrer forwarding. Protected Page sign-in forwards the browser language; residual GitHub-only error wording was made provider-neutral.
  • Added concurrent refresh, rollback fault injection, expired-flow, strict eight-digit input, leading-zero preservation, and frontend failure-state tests. Local relay transport regression checks email/GitHub account isolation through real local sockets and a mock identity authority. Native phone paths were reviewed statically in this follow-up; no new physical-device run is claimed.

This follow-up updates source and tests. Production remains on the previously deployed revision until the next deployment.

@bobleer
bobleer merged commit 562cad6 into GCWing:main Sep 15, 2026
14 checks passed
@bobleer
bobleer deleted the bob/email-code-login branch September 24, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant