docs(federation/auth/api/db/client): detached-account re-attach flow; reset-cleanup panel mentions re-attach

This commit is contained in:
Jannis Braun
2026-07-03 02:28:35 +02:00
parent 344a429e98
commit 521aff6e52
4 changed files with 18 additions and 0 deletions
+2
View File
@@ -302,6 +302,8 @@ Trade-off: the separate authenticated call can fail independently of the login P
Detach is sovereign but not permanent: the legitimate owner who re-created their account on the reset home can re-bind the detached account to the new home identity via `POST /api/users/@me/reattach` (registered in `routes/federation.ts`; see `federation.md` "Peer-Side Re-Attach"). It re-binds **only** on possession of BOTH identities — the session IS the detached account (local password authority, via `authenticate`) AND a one-time proof token minted on the home via `POST /api/auth/attach-proof` verifies with the home peer over signed S2S. Identity is never username-matched (that is the tier-2 hijack). On success the endpoint merges any pre-existing replicated stub for the new identity into the detached row, sets `home_user_id = <new homeUserId>`, **clears `federation_home_orphaned` (0)**, nulls `profile_updated_at`, and applies the current home profile. Clearing the flag automatically **re-enables** normal federated-account semantics: login self-heal resumes (the epoch guard above runs again) and the S2S binding guards stop excluding the account — live profile/presence sync from the home is restored. The local password hash is kept; a detached tombstone (`is_deleted = 1`) is never re-attachable.
**Proof-mint endpoint — `POST /api/auth/attach-proof`** (`routes/auth.ts`). The home-side half of the exchange, run against the owner's re-created **native** account on the reset home. JWT-authenticated, rate-limited 5/15min. Body `{ targetDomain }` names the peer the caller intends to re-attach on. Guards: the session user must be **native** (`homeInstance` null) — a federated/replicated session cannot mint a proof for itself. Mints a random 256-bit token (`randomBytes(32).toString('hex')`), inserts a `federation_attach_proofs` row `{ homeUserId, targetDomain, createdAt, expiresAt = now + 60s, usedAt: null }`, and returns `{ token }`. The token is **single-use, 60s TTL, and bound to `targetDomain`** — only the named peer can redeem it (verified server-side against the authenticated peer domain, not the request body, at `POST /api/federation/verify-attach-proof`). Each mint opportunistically janitors expired rows (`DELETE ... WHERE expires_at < now`); since the TTL is 60s, any spent (`used_at` set) token is swept on the next mint after it expires, so the table stays bounded without a background worker.
---
## 5. Password Change