feat(federation): detached accounts get local profile+password self-service; self-view flag (detach spec §4.4, §4.7)
This commit is contained in:
+3
-1
@@ -47,7 +47,9 @@ GET /users/:id → { user }
|
||||
GET /users/:id/mutuals ?homeUserId= → { mutualFriends[], mutualSpaces[] }
|
||||
```
|
||||
|
||||
**Write protection:** If the authenticated user is a replicated user (`homeInstance` is set), the following fields are rejected with 403: `displayName`, `avatar`, `banner`, `accentColor`, `avatarColor`, `bio`. These fields are managed by the home instance via S2S relay.
|
||||
**Write protection:** If the authenticated user is a replicated user (`homeInstance` is set **and** `federationHomeOrphaned !== 1`), the following fields are rejected with 403: `displayName`, `avatar`, `banner`, `accentColor`, `avatarColor`, `bio`. These fields are managed by the home instance via S2S relay. **Exception — detached accounts** (`federationHomeOrphaned === 1`): a federated account whose home instance was reset/lost is a sovereign local account with no home managing its profile, so it edits these durable fields locally like a native user (detach design §4.4). Detached edits are NOT relayed (the S2S profile-relay path stays gated on `!homeInstance`).
|
||||
|
||||
**Self-view flag:** `GET /users/@me`, the login response, and the WS `ready` payload all sanitize the row with `isSelf=true` and include `federationHomeOrphaned: boolean` (detach design §4.7) — self-view only; it is never exposed to other users and never on the deleted/tombstone branch.
|
||||
|
||||
## Spaces (`routes/spaces.ts`) — auth required
|
||||
```
|
||||
|
||||
@@ -313,12 +313,13 @@ Trade-off: the separate authenticated call can fail independently of the login P
|
||||
| User type | `currentPassword` | Behavior |
|
||||
|-----------|-------------------|----------|
|
||||
| Local (`homeInstance` is null) | Required | Verified via bcrypt against stored hash |
|
||||
| Federated (`homeInstance` set) | Not required | JWT auth is sufficient (home instance already verified the change) |
|
||||
| Federated (`homeInstance` set, `federationHomeOrphaned !== 1`) | Not required | JWT auth is sufficient (home instance already verified the change) |
|
||||
| Detached (`homeInstance` set, `federationHomeOrphaned === 1`) | Required | Follows the **local** rule — the home is gone, so nothing external verified the change; the local hash is the sole authority (detach design §4.4) |
|
||||
|
||||
**Steps:**
|
||||
1. Validate `newPassword` is string, min 8 chars
|
||||
2. Load user from DB
|
||||
3. If local: require and verify `currentPassword`
|
||||
3. If local **or detached** (`!homeInstance || federationHomeOrphaned === 1`): require and verify `currentPassword`
|
||||
4. Hash new password
|
||||
5. Update `passwordHash` AND `passwordChangedAt = Date.now()` -- this invalidates all prior tokens
|
||||
6. Sign fresh JWT, return `{ token }`
|
||||
|
||||
Reference in New Issue
Block a user