feat(profile): sign-in methods matrix — email add/change, provider link/unlink

Profile shows the account's sign-in methods for guests and durable accounts alike:
add or change email, link Telegram on the web (login widget), and unlink a linked
provider. Email is never unlinked (it is changed); unlink is offered only when
another identity remains, and a change to an address owned by another account shows
the non-disclosing 'check the address or contact support'. Add-VK-on-web stays
deferred (no VK OAuth).

Wires linkUnlink / changeEmailRequest / changeEmailConfirm through the client,
transport, mock and codec (encodeLinkUnlink + LinkResult 'unlinked'/'changed'
statuses); codec wire tests; ru/en i18n.
This commit is contained in:
Ilia Denisov
2026-07-03 09:57:05 +02:00
parent b918217497
commit e4fc7f033d
9 changed files with 269 additions and 24 deletions
+8
View File
@@ -177,6 +177,14 @@ export interface GatewayClient {
linkEmailMerge(email: string, code: string): Promise<LinkResult>;
linkTelegram(data: string): Promise<LinkResult>;
linkTelegramMerge(data: string): Promise<LinkResult>;
/** Detach a platform identity (kind 'telegram' | 'vk') from the account; email is never
* unlinked. Returns the refreshed link result (status 'unlinked'). */
linkUnlink(kind: string): Promise<LinkResult>;
/** Change the account's confirmed email: mail a code to the new address, then confirm
* to atomically switch (status 'changed'). A new address owned by another account is
* refused without disclosure. */
changeEmailRequest(email: string): Promise<void>;
changeEmailConfirm(email: string, code: string): Promise<LinkResult>;
// --- live stream ---
subscribe(onEvent: (e: PushEvent) => void, onError?: (err: unknown) => void): Unsubscribe;