From 4fa241493390920dd999f1d21ae839f470a28001 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:35:34 +0200 Subject: [PATCH] fix(presence): drop status='online' from registration insert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors the REST-login change in f17c46c on the registration insert path. A successful POST /api/auth/register does not by itself imply a live WebSocket — the client may never connect (transient network, mobile background, error path between the 201 and /ws), leaving a permanently stuck-online row that no disconnect timer can clean up. The schema default 'offline' is correct; ws/handler.ts flips it to 'online' on real WS auth. The federated-stub upgrade path in the same handler is unaffected: it only updates passwordHash/username/homeUserId/displayName/avatarColor, leaving the stub's pre-existing 'offline' status (set when the stub was created via replication) untouched. Updates docs/systems/auth.md step 7 to reflect the new behavior. --- docs/systems/auth.md | 2 +- packages/server/src/routes/auth.ts | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/systems/auth.md b/docs/systems/auth.md index e5b50248..79dad638 100644 --- a/docs/systems/auth.md +++ b/docs/systems/auth.md @@ -149,7 +149,7 @@ If `requestedAvatarColor` is provided and is in `AVATAR_COLORS`, use it. Otherwi 4. Check username uniqueness (exact match on lowercased username) 5. Hash password (bcrypt, 12 rounds) 6. Generate Snowflake ID -7. Insert user row with `status: 'online'`, admin flag if first user +7. Insert user row (status defaults to `'offline'` at the schema level; it is set to `'online'` only when the client establishes a WebSocket via the WS auth path in `ws/handler.ts`). Admin flag set if first user. 8. Sign JWT with `{ userId, username }` 9. Return `{ token, user }` (user sanitized via `sanitizeUser(user, true)`) diff --git a/packages/server/src/routes/auth.ts b/packages/server/src/routes/auth.ts index 445ffa63..be717e38 100644 --- a/packages/server/src/routes/auth.ts +++ b/packages/server/src/routes/auth.ts @@ -166,12 +166,19 @@ export async function authRoutes(app: FastifyInstance): Promise { ? requestedAvatarColor : AVATAR_COLORS[Math.floor(Math.random() * AVATAR_COLORS.length)]; + // Note: status is left at the schema default ('offline') and is set to + // 'online' exclusively by the WebSocket auth path (ws/handler.ts). A + // successful REST /register does not by itself imply a live connection — + // the client may never establish a WS (transient network failure, mobile + // background, error path between this 201 response and /ws connect), + // which would otherwise produce a permanently stuck-online row that no + // disconnect timer can clean up. The WS handshake will flip it to + // 'online' once a real socket attaches. db.insert(schema.users).values({ id: userId, username: trimmedUsername, displayName: displayName?.trim() || null, passwordHash, - status: 'online', isAdmin: isFirstUser ? 1 : 0, homeInstance: homeInstance || null, homeUserId: (homeInstance && homeUserId && typeof homeUserId === 'string') ? homeUserId : null,