@luckystack/server 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ All notable changes to `@luckystack/server` are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.15.0] - 2026-10-19
9
+
10
+ ### Changed
11
+
12
+ - **Breaking:** `/auth/api/<credentials provider>` (login and register) accepts only POST and answers other methods with 405. This blocks login CSRF through a cross-site GET and keeps passwords out of URLs. Upgrade: a caller that logs in with GET must switch to POST; the shipped LoginForm already does.
13
+ - **Breaking:** login responses (`/auth/api/credentials`, `/auth/api/email-code/verify`, `/auth/api/2fa`) no longer contain `session.token` or `session.csrfToken` in the JSON body. Upgrade: read the token from the `X-Session-Token` header (token mode) and get the CSRF token from `/auth/csrf`.
14
+ - **Breaking:** only for projects that set `http.sessionCookiePrefix` (`'__Host-'` / `'__Secure-'`) or `http.sessionCookieDomain`. Both settings are now applied: login, OAuth callback, email-code and 2FA, sliding refresh and logout write the session cookie with the same name, Path, Domain and Secure rules (ADR 0078). The cookie name and attributes change, so every user is logged out once after the upgrade. Other projects see no change.
15
+
16
+ ### Fixed
17
+
18
+ - **An anonymous socket client can no longer crash the server process** by sending `joinRoom`, `leaveRoom`, `getJoinedRooms`, `syncCancel`, `apiCancel` or `updateLocation` without a payload or with `null`. These events ignore a missing or non-object payload.
19
+ - **A room join or leave, or a location update, that overlaps a logout, session revoke or "sign out everywhere" no longer brings the deleted session back.** The update is dropped and the client gets `session.notFound` (ADR 0077).
20
+ - **HTTP API POST, PUT and DELETE calls keep a body field named `stream`.** Only the `?stream=` flag of a GET is removed.
21
+ - **After a dev port hop, the `listen` callback, the "Server is running" log and the dev-server advertisement run once**, instead of once per busy port plus one.
22
+ - **A normal graceful shutdown no longer logs** `[shutdown] step "io-close" failed: Server is not running.`
23
+ - **A generated runtime-maps preset that fails to load logs the real error and is retried on the next request**, instead of staying failed until the process restarts.
24
+ - **`preHttpRequest` hook headers leave out a renamed CSRF header** (set with `registerCsrfConfig({ headerName })`) and `proxy-authorization`.
25
+ - **The `onSocketConnect` hook's `ip` honours `http.trustProxy`.**
26
+ - **Top-level static files requested with a query string** (`/logo.png?v=2`) are served instead of answering 404.
27
+ - **`joinRoom('all')` is refused with `room.invalid`**, and a persisted `'all'` room is skipped when a session's rooms are re-joined on connect. `'all'` is the sync "every socket" receiver, so a real room with that name would be mistaken for everyone.
28
+
8
29
  ## [0.12.0] - 2026-10-15
9
30
 
10
31
  ### Changed
@@ -13,6 +13,7 @@
13
13
  export interface OnSocketConnectPayload {
14
14
  socketId: string;
15
15
  token: string | null;
16
+ /** Resolved client IP (honours `http.trustProxy`). */
16
17
  ip: string;
17
18
  }
18
19
  export interface OnSocketDisconnectPayload {
@@ -1,3 +1,4 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import type { CreateLuckyStackServerOptions } from './types.js';
3
+ export declare const buildHookSafeHeaders: (headers: IncomingMessage['headers']) => Record<string, string>;
3
4
  export declare const handleHttpRequest: (req: IncomingMessage, res: ServerResponse, options: CreateLuckyStackServerOptions) => Promise<void>;
@@ -0,0 +1 @@
1
+ export declare const toClientSession: (session: unknown) => unknown;
@@ -1 +1,9 @@
1
1
  export declare const resolveCookieSecure: (sessionCookieSecure: boolean | undefined, secureEnv: string | undefined) => boolean;
2
+ /** Effective session cookie name: `http.sessionCookieName` plus any `__Host-`/`__Secure-` prefix. */
3
+ export declare const resolveSessionCookieName: () => string;
4
+ /** Attribute string for the session cookie with the given lifetime (0 clears it). */
5
+ export declare const buildSessionCookieOptions: (maxAgeSeconds: number) => string;
6
+ /** Full `Set-Cookie` value carrying `token` under the effective session cookie name. */
7
+ export declare const buildSessionCookie: (token: string, cookieOptions: string) => string;
8
+ /** `Set-Cookie` value that expires the session cookie (same name, Path and Domain as when set). */
9
+ export declare const buildClearedSessionCookie: () => string;