docs+test(email): document the confirm deeplink + wire-contract tests
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 16s
CI / ui (pull_request) Successful in 1m3s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m52s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 16s
CI / ui (pull_request) Successful in 1m3s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m52s
Document the one-tap confirm deeplink in ARCHITECTURE (§4 the login magic-link / link confirm+profile-refresh, prefetch-safe token) and the new notify 'profile' sub-kind (§10), and add the one-tap link to the FUNCTIONAL email story (+ru). Add codec round-trip assertions for the EmailRequest language field and encodeEmailConfirmLink (the mock e2e bypasses the codec).
This commit is contained in:
+11
-2
@@ -239,7 +239,13 @@ arrive from a platform rather than completing a mandatory registration).
|
||||
development log mailer when no relay is configured) and, once
|
||||
verified, attaches a confirmed email identity. Sends are throttled per recipient
|
||||
(a 60-second cooldown and a five-per-hour cap). Links in the email are built from
|
||||
a configured public base URL, never a request Host header (anti-injection). An
|
||||
a configured public base URL, never a request Host header (anti-injection). The email
|
||||
also carries a **one-tap confirm deeplink** (`/app/#/confirm/<token>`, an opaque
|
||||
256-bit token stored only as its SHA-256, 12-hour TTL): a login mints a session in the
|
||||
browser that opens it (magic-link), a link confirms the identity and emits a `notify`
|
||||
profile-refresh to the in-app session, and a would-be merge is deferred to the
|
||||
interactive flow. The confirm page is prefetch-safe — it confirms only on a button
|
||||
press, so a mail scanner's GET does not consume the single-use token. An
|
||||
**email-login** account is created flagged `is_guest` and stays reapable until the
|
||||
code is confirmed — so an abandoned, never-confirmed login frees its reserved
|
||||
address — with confirming clearing the flag. Accounts and identities use
|
||||
@@ -933,7 +939,10 @@ edge-pause, scroll speed, and the fade-out → gap → fade-in transition) are o
|
||||
eligibility inputs (grants hints, grants/revokes `no_banner`; a future payment flow sets
|
||||
`paid_account`), the backend emits a `notify` **`banner`** sub-kind (a payload-free re-poll signal),
|
||||
and the open client re-fetches `profile.get` to show or hide the banner in place. Operator *content*
|
||||
edits take effect on the next `profile.get` (open/reconnect/foreground), not mid-session.
|
||||
edits take effect on the next `profile.get` (open/reconnect/foreground), not mid-session. The same
|
||||
mechanism carries a **`profile`** sub-kind — a payload-free re-fetch signal emitted when a viewer's
|
||||
own account changed out of band (an email confirmed through the one-tap deeplink opened in another
|
||||
browser), so an open in-app session reflects it at once.
|
||||
|
||||
> A single `app.load` bootstrap aggregator (collapsing `profile.get` + lobby + badge fetches into
|
||||
> one round-trip) was **considered and deferred**: client↔gateway is HTTP/2 (h2c), so the bootstrap
|
||||
|
||||
Reference in New Issue
Block a user