@proteinjs/server 3.5.1 → 3.5.3

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
@@ -3,6 +3,28 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.5.3](https://github.com/proteinjs/server/compare/@proteinjs/server@3.5.2...@proteinjs/server@3.5.3) (2026-09-01)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **server:** the react-app HTML response says Cache-Control: no-cache — the page always revalidates (found live 2026-09-01, the mobile-app stale-page investigation). The '*' route sent HTML with an ETag but NO Cache-Control: with no explicit policy, HTTP heuristic caching applies (RFC 9111 §4.2.2) and WKWebView in particular can serve the cached page without revalidating — across app force-quits — pinning stale bundle POINTERS long after a deploy. The hashed bundles under /static keep their long cache (a fresh page always points at fresh hashes); the PAGE must always revalidate. no-cache + the ETag express already stamps = a cheap 304 on every load, never a stale page. Red-before-green: htmlCacheControl.test.ts (front door — a real spawned server, the LB's X-Forwarded-Proto topology) read cache-control undefined at the pre-fix dist (2 red), green after; / and /chat both pinned (the catch-all is the one HTML owner). Fixture gains a bundlePaths pointer so the react-app route serves its page; full estate 5 suites / 11 green (9 pre-existing). ([076536f](https://github.com/proteinjs/server/commit/076536f158ce1c91b073061345fe7aae802b4f38))
12
+
13
+
14
+
15
+
16
+
17
+ ## [3.5.2](https://github.com/proteinjs/server/compare/@proteinjs/server@3.5.1...@proteinjs/server@3.5.2) (2026-08-27)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * a request always seeds its OWN session context — kills the keep-alive session-bag bleed ([24f84e3](https://github.com/proteinjs/server/commit/24f84e38cdc4317e5e2c5ef819ed8d58289cfc5b))
23
+
24
+
25
+
26
+
27
+
6
28
  ## [3.5.1](https://github.com/proteinjs/server/compare/@proteinjs/server@3.5.0...@proteinjs/server@3.5.1) (2026-08-19)
7
29
 
8
30
 
@@ -33,7 +33,7 @@ require("react-helmet");
33
33
  require("socket.io");
34
34
  require("typescript");
35
35
  /** Generate Source Graph */
36
- var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeGlobalDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeGlobalDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeGlobalDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"GLOBAL_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: GlobalData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: GlobalData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/GlobalDataStorage\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeSessionDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeSessionDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeSessionDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SESSION_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: SessionData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: SessionData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/SessionDataStorage\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"properties\":[{\"name\":\"sessionID\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"user\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"http\",\"name\":\"IncomingMessage\",\"filePath\":null,\"qualifiedName\":\"http/IncomingMessage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"http/IncomingMessage\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedSocket\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedSocket\",\"properties\":[{\"name\":\"request\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"socket.io\",\"name\":\"Socket\",\"filePath\":null,\"qualifiedName\":\"socket.io/Socket\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"socket.io/Socket\"},{\"v\":\"@proteinjs/server/environmentCache\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"environmentCache\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/envCache.ts\",\"qualifiedName\":\"@proteinjs/server/environmentCache\",\"type\":{\"packageName\":\"\",\"name\":\"GlobalDataCache<Env>\",\"filePath\":null,\"qualifiedName\":\"/GlobalDataCache<Env>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataCache\",\"typeParameters\":[\"@proteinjs/server-api/Env\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/GlobalDataCache\"},{\"v\":\"@proteinjs/server/healthCheck\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"healthCheck\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/routes/healthCheck.ts\",\"qualifiedName\":\"@proteinjs/server/healthCheck\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"}],\"edges\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"w\":\"@proteinjs/server-api/GlobalDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"w\":\"@proteinjs/server-api/SessionDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"w\":\"http/IncomingMessage\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"w\":\"socket.io/Socket\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/environmentCache\",\"w\":\"@proteinjs/server-api/GlobalDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/server/healthCheck\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
36
+ var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeGlobalDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeGlobalDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeGlobalDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"GLOBAL_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: GlobalData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: GlobalData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/GlobalDataStorage\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeSessionDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeSessionDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeSessionDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SESSION_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: SessionData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: SessionData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"clearData\",\"returnType\":{\"packageName\":\"\",\"name\":\"void\",\"filePath\":null,\"qualifiedName\":\"/void\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/SessionDataStorage\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"properties\":[{\"name\":\"sessionID\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"user\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"http\",\"name\":\"IncomingMessage\",\"filePath\":null,\"qualifiedName\":\"http/IncomingMessage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"http/IncomingMessage\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedSocket\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedSocket\",\"properties\":[{\"name\":\"request\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"socket.io\",\"name\":\"Socket\",\"filePath\":null,\"qualifiedName\":\"socket.io/Socket\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"socket.io/Socket\"},{\"v\":\"@proteinjs/server/environmentCache\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"environmentCache\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/envCache.ts\",\"qualifiedName\":\"@proteinjs/server/environmentCache\",\"type\":{\"packageName\":\"\",\"name\":\"GlobalDataCache<Env>\",\"filePath\":null,\"qualifiedName\":\"/GlobalDataCache<Env>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataCache\",\"typeParameters\":[\"@proteinjs/server-api/Env\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/GlobalDataCache\"},{\"v\":\"@proteinjs/server/healthCheck\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"healthCheck\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/routes/healthCheck.ts\",\"qualifiedName\":\"@proteinjs/server/healthCheck\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"}],\"edges\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"w\":\"@proteinjs/server-api/GlobalDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"w\":\"@proteinjs/server-api/SessionDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"w\":\"http/IncomingMessage\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"w\":\"socket.io/Socket\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/environmentCache\",\"w\":\"@proteinjs/server-api/GlobalDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/server/healthCheck\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
37
37
  /** Generate Source Links */
38
38
  var NodeGlobalDataStorage_1 = require("../src/NodeGlobalDataStorage");
39
39
  var NodeSessionDataStorage_1 = require("../src/NodeSessionDataStorage");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,4BAA0B;AAC1B,6BAA2B;AAC3B,iCAA+B;AAC/B,iCAA+B;AAC/B,gCAA8B;AAC9B,uBAAqB;AACrB,yBAAuB;AACvB,kBAAgB;AAChB,mBAAiB;AACjB,2BAAyB;AACzB,oBAAkB;AAClB,0BAAwB;AACxB,mBAAiB;AACjB,iBAAe;AACf,wBAAsB;AACtB,qBAAmB;AACnB,sBAAoB;AAGpB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,gqRAAgqR,CAAC;AAGrrR,4BAA4B;AAE5B,sEAAqE;AACrE,wEAAuE;AACvE,4CAAmD;AACnD,yDAAwD;AAExD,IAAM,WAAW,GAAG;IACnB,yCAAyC,EAAE,6CAAqB;IAChE,0CAA0C,EAAE,+CAAsB;IAClE,oCAAoC,EAAE,2BAAgB;IACtD,+BAA+B,EAAE,yBAAW;CAC5C,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,4BAA0B;AAC1B,6BAA2B;AAC3B,iCAA+B;AAC/B,iCAA+B;AAC/B,gCAA8B;AAC9B,uBAAqB;AACrB,yBAAuB;AACvB,kBAAgB;AAChB,mBAAiB;AACjB,2BAAyB;AACzB,oBAAkB;AAClB,0BAAwB;AACxB,mBAAiB;AACjB,iBAAe;AACf,wBAAsB;AACtB,qBAAmB;AACnB,sBAAoB;AAGpB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,y8RAAy8R,CAAC;AAG99R,4BAA4B;AAE5B,sEAAqE;AACrE,wEAAuE;AACvE,4CAAmD;AACnD,yDAAwD;AAExD,IAAM,WAAW,GAAG;IACnB,yCAAyC,EAAE,6CAAqB;IAChE,0CAA0C,EAAE,+CAAsB;IAClE,oCAAoC,EAAE,2BAAgB;IACtD,+BAA+B,EAAE,yBAAW;CAC5C,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
@@ -5,6 +5,17 @@ export declare class NodeSessionDataStorage implements SessionDataStorage {
5
5
  environment: "node";
6
6
  setData(data: SessionData): void;
7
7
  getData(): SessionData;
8
+ /**
9
+ * Drop the CURRENT async id's entry so the next `setData` seeds fresh. The init hook copies
10
+ * a populated bag onto every descendant async resource and `setData` is first-write-wins, so
11
+ * a request dispatched inside a PREVIOUS request's lineage (keep-alive socket reuse — the
12
+ * normal case under a 620s keepAliveTimeout) would otherwise run as the prior request's user
13
+ * (observed 2026-08-26: /dev/login account switch, home greeting server-rendered with the
14
+ * previous account's name). Scoped to the current id on purpose: in-flight hops of the
15
+ * previous request keep their own already-copied entries, and descendants created after the
16
+ * re-seed inherit the fresh bag.
17
+ */
18
+ clearData(): void;
8
19
  private initHook;
9
20
  }
10
21
  //# sourceMappingURL=NodeSessionDataStorage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NodeSessionDataStorage.d.ts","sourceRoot":"","sources":["../../src/NodeSessionDataStorage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAExE,qBAAa,sBAAuB,YAAW,kBAAkB;IAC/D,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAS;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAqC;IACzE,WAAW,SAAoB;IAE/B,OAAO,CAAC,IAAI,EAAE,WAAW;IAYzB,OAAO,IAAI,WAAW;IAQtB,OAAO,CAAC,QAAQ;CAiBjB"}
1
+ {"version":3,"file":"NodeSessionDataStorage.d.ts","sourceRoot":"","sources":["../../src/NodeSessionDataStorage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAExE,qBAAa,sBAAuB,YAAW,kBAAkB;IAC/D,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAS;IACxC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAqC;IACzE,WAAW,SAAoB;IAE/B,OAAO,CAAC,IAAI,EAAE,WAAW;IAYzB,OAAO,IAAI,WAAW;IAQtB;;;;;;;;;OASG;IACH,SAAS,IAAI,IAAI;IAQjB,OAAO,CAAC,QAAQ;CAiBjB"}
@@ -24,6 +24,22 @@ var NodeSessionDataStorage = /** @class */ (function () {
24
24
  }
25
25
  return NodeSessionDataStorage.SESSION_DATA[async_hooks_1.default.executionAsyncId()];
26
26
  };
27
+ /**
28
+ * Drop the CURRENT async id's entry so the next `setData` seeds fresh. The init hook copies
29
+ * a populated bag onto every descendant async resource and `setData` is first-write-wins, so
30
+ * a request dispatched inside a PREVIOUS request's lineage (keep-alive socket reuse — the
31
+ * normal case under a 620s keepAliveTimeout) would otherwise run as the prior request's user
32
+ * (observed 2026-08-26: /dev/login account switch, home greeting server-rendered with the
33
+ * previous account's name). Scoped to the current id on purpose: in-flight hops of the
34
+ * previous request keep their own already-copied entries, and descendants created after the
35
+ * re-seed inherit the fresh bag.
36
+ */
37
+ NodeSessionDataStorage.prototype.clearData = function () {
38
+ if (!NodeSessionDataStorage.HOOK_INITIALIZED) {
39
+ this.initHook();
40
+ }
41
+ delete NodeSessionDataStorage.SESSION_DATA[async_hooks_1.default.executionAsyncId()];
42
+ };
27
43
  NodeSessionDataStorage.prototype.initHook = function () {
28
44
  async_hooks_1.default
29
45
  .createHook({
@@ -1 +1 @@
1
- {"version":3,"file":"NodeSessionDataStorage.js","sourceRoot":"","sources":["../../src/NodeSessionDataStorage.ts"],"names":[],"mappings":";;;;;;AAAA,4DAAqC;AAGrC;IAAA;QAGE,gBAAW,GAAG,MAAgB,CAAC;IAuCjC,CAAC;IArCC,wCAAO,GAAP,UAAQ,IAAiB;QACvB,IAAI,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;YAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;SACjB;QAED,IAAI,sBAAsB,CAAC,YAAY,CAAC,qBAAU,CAAC,gBAAgB,EAAE,CAAC,EAAE;YACtE,OAAO;SACR;QAED,sBAAsB,CAAC,YAAY,CAAC,qBAAU,CAAC,gBAAgB,EAAE,CAAC,GAAG,IAAI,CAAC;IAC5E,CAAC;IAED,wCAAO,GAAP;QACE,IAAI,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;YAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;SACjB;QAED,OAAO,sBAAsB,CAAC,YAAY,CAAC,qBAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC5E,CAAC;IAEO,yCAAQ,GAAhB;QACE,qBAAU;aACP,UAAU,CAAC;YACV,IAAI,EAAE,UAAC,OAAe,EAAE,IAAY,EAAE,cAAsB,EAAE,QAAgB;gBAC5E,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE;oBACxD,OAAO;iBACR;gBAED,sBAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;YACrG,CAAC;YACD,OAAO,EAAE,UAAC,OAAe;gBACvB,OAAO,sBAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YACtD,CAAC;SACF,CAAC;aACD,MAAM,EAAE,CAAC;QACZ,sBAAsB,CAAC,gBAAgB,GAAG,IAAI,CAAC;IACjD,CAAC;IAxCc,uCAAgB,GAAG,KAAK,AAAR,CAAS;IAChB,mCAAY,GAAkC,EAAE,AAApC,CAAqC;IAwC3E,6BAAC;CAAA,AA1CD,IA0CC;AA1CY,wDAAsB"}
1
+ {"version":3,"file":"NodeSessionDataStorage.js","sourceRoot":"","sources":["../../src/NodeSessionDataStorage.ts"],"names":[],"mappings":";;;;;;AAAA,4DAAqC;AAGrC;IAAA;QAGE,gBAAW,GAAG,MAAgB,CAAC;IAyDjC,CAAC;IAvDC,wCAAO,GAAP,UAAQ,IAAiB;QACvB,IAAI,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;YAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;SACjB;QAED,IAAI,sBAAsB,CAAC,YAAY,CAAC,qBAAU,CAAC,gBAAgB,EAAE,CAAC,EAAE;YACtE,OAAO;SACR;QAED,sBAAsB,CAAC,YAAY,CAAC,qBAAU,CAAC,gBAAgB,EAAE,CAAC,GAAG,IAAI,CAAC;IAC5E,CAAC;IAED,wCAAO,GAAP;QACE,IAAI,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;YAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;SACjB;QAED,OAAO,sBAAsB,CAAC,YAAY,CAAC,qBAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED;;;;;;;;;OASG;IACH,0CAAS,GAAT;QACE,IAAI,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;YAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;SACjB;QAED,OAAO,sBAAsB,CAAC,YAAY,CAAC,qBAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC5E,CAAC;IAEO,yCAAQ,GAAhB;QACE,qBAAU;aACP,UAAU,CAAC;YACV,IAAI,EAAE,UAAC,OAAe,EAAE,IAAY,EAAE,cAAsB,EAAE,QAAgB;gBAC5E,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE;oBACxD,OAAO;iBACR;gBAED,sBAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,sBAAsB,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;YACrG,CAAC;YACD,OAAO,EAAE,UAAC,OAAe;gBACvB,OAAO,sBAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YACtD,CAAC;SACF,CAAC;aACD,MAAM,EAAE,CAAC;QACZ,sBAAsB,CAAC,gBAAgB,GAAG,IAAI,CAAC;IACjD,CAAC;IA1Dc,uCAAgB,GAAG,KAAK,AAAR,CAAS;IAChB,mCAAY,GAAkC,EAAE,AAApC,CAAqC;IA0D3E,6BAAC;CAAA,AA5DD,IA4DC;AA5DY,wDAAsB"}
@@ -126,6 +126,13 @@ function wrapRoute(route, config) {
126
126
  _i++;
127
127
  return [3 /*break*/, 1];
128
128
  case 4:
129
+ // A request always seeds ITS OWN session context: on a reused keep-alive socket this
130
+ // dispatch is born inside the previous request's async lineage (the storage's init hook
131
+ // copies bags onto descendants), and first-write-wins setData would silently drop this
132
+ // request's seed — the request then runs (and server-renders proteinjs.sessionData) as
133
+ // the PRIOR request's user (observed 2026-08-26: stale home greeting after a /dev/login
134
+ // account switch; roster correct, greeting wrong). Clear the inherited entry first.
135
+ server_api_1.Session.clearData();
129
136
  server_api_1.Session.setData(sessionData);
130
137
  if (shouldLogRequest(request, config)) {
131
138
  message = "Started ".concat(request.originalUrl);
@@ -1 +1 @@
1
- {"version":3,"file":"loadRoutes.js","sourceRoot":"","sources":["../../src/loadRoutes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loadRoutes.js","sourceRoot":"","sources":["../../src/loadRoutes.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"reactApp.d.ts","sourceRoot":"","sources":["../../../src/routes/reactApp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAA4B,MAAM,uBAAuB,CAAC;AAU/E,eAAO,MAAM,cAAc,iBAAkB,YAAY;;;yBAI1B,GAAG,YAAY,GAAG,KAAG,QAAQ,IAAI,CAAC;CA+BhE,CAAC"}
1
+ {"version":3,"file":"reactApp.d.ts","sourceRoot":"","sources":["../../../src/routes/reactApp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAA4B,MAAM,uBAAuB,CAAC;AAU/E,eAAO,MAAM,cAAc,iBAAkB,YAAY;;;yBAI1B,GAAG,YAAY,GAAG,KAAG,QAAQ,IAAI,CAAC;CAsChE,CAAC"}
@@ -67,6 +67,13 @@ var createReactApp = function (serverConfig) {
67
67
  throw new Error("ServerConfig.bundlePath or ServerConfig.bundlesDir must be provided to serve a react app");
68
68
  }
69
69
  helmet = react_helmet_1.default.renderStatic();
70
+ // The page must ALWAYS revalidate (found live 2026-09-01, the mobile-app stale-page
71
+ // investigation): without an explicit policy, HTTP heuristic caching applies (RFC 9111
72
+ // §4.2.2) — WKWebView in particular can serve the cached page without revalidating,
73
+ // across app force-quits, pinning stale bundle POINTERS long after a deploy. The hashed
74
+ // bundles under /static keep their long cache (a fresh page always points at fresh
75
+ // hashes); `no-cache` + the ETag express already stamps = a cheap 304 on every load.
76
+ response.set('Cache-Control', 'no-cache');
70
77
  _b = (_a = response).send;
71
78
  _e = (_d = "<!DOCTYPE html>\n <html ".concat(helmet.htmlAttributes, ">\n <head>\n <meta charset='utf-8' />\n <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1, viewport-fit=cover'>\n <meta name='theme-color' content='").concat(THEME_COLOR_LIGHT, "' media='(prefers-color-scheme: light)'>\n <meta name='theme-color' content='").concat(THEME_COLOR_DARK, "' media='(prefers-color-scheme: dark)'>\n <link href='").concat(((_j = serverConfig.staticContent) === null || _j === void 0 ? void 0 : _j.faviconPath) ? path_1.default.join('/static/', serverConfig.staticContent.faviconPath) : '', "' rel='icon' type='image/png' />\n ").concat(helmet.title.toString(), "\n ").concat(helmet.meta.toString(), "\n ").concat(helmet.link.toString(), "\n </head>\n <body ").concat(helmet.bodyAttributes.toString(), ">\n <div id='app'></div>\n <script>proteinjs = {};</script>\n ")).concat;
72
79
  return [4 /*yield*/, serverRenderedScriptTags()];
@@ -1 +1 @@
1
- {"version":3,"file":"reactApp.js","sourceRoot":"","sources":["../../../src/routes/reactApp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reactApp.js","sourceRoot":"","sources":["../../../src/routes/reactApp.ts"],"names":[],"mappings":"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"}
@@ -21,7 +21,7 @@ import 'typescript';
21
21
  /** Generate Source Graph */
22
22
 
23
23
  const sourceGraph =
24
- '{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/server/NodeGlobalDataStorage","value":{"packageName":"@proteinjs/server","name":"NodeGlobalDataStorage","filePath":"/home/runner/work/server/server/packages/server/src/NodeGlobalDataStorage.ts","qualifiedName":"@proteinjs/server/NodeGlobalDataStorage","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"HOOK_INITIALIZED","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"GLOBAL_DATA","type":{"packageName":"@proteinjs/server","name":"{ [id: string]: GlobalData }","filePath":null,"qualifiedName":"@proteinjs/server/{ [id: string]: GlobalData }","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"environment","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"setData","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"data","type":{"packageName":"@proteinjs/server-api","name":"GlobalData","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalData","typeParameters":null,"directParents":null}}]},{"name":"getData","returnType":{"packageName":"@proteinjs/server-api","name":"GlobalData","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalData","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"initHook","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/server-api","name":"GlobalDataStorage","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalDataStorage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/server-api/GlobalDataStorage"},{"v":"@proteinjs/server/NodeSessionDataStorage","value":{"packageName":"@proteinjs/server","name":"NodeSessionDataStorage","filePath":"/home/runner/work/server/server/packages/server/src/NodeSessionDataStorage.ts","qualifiedName":"@proteinjs/server/NodeSessionDataStorage","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"HOOK_INITIALIZED","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SESSION_DATA","type":{"packageName":"@proteinjs/server","name":"{ [id: string]: SessionData }","filePath":null,"qualifiedName":"@proteinjs/server/{ [id: string]: SessionData }","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"environment","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"setData","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"data","type":{"packageName":"@proteinjs/server-api","name":"SessionData","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionData","typeParameters":null,"directParents":null}}]},{"name":"getData","returnType":{"packageName":"@proteinjs/server-api","name":"SessionData","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionData","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"initHook","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/server-api","name":"SessionDataStorage","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionDataStorage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/server-api/SessionDataStorage"},{"v":"@proteinjs/server/ExtendedIncomingMessage","value":{"packageName":"@proteinjs/server","name":"ExtendedIncomingMessage","filePath":"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts","qualifiedName":"@proteinjs/server/ExtendedIncomingMessage","properties":[{"name":"sessionID","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"user","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParents":[{"packageName":"http","name":"IncomingMessage","filePath":null,"qualifiedName":"http/IncomingMessage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"sourceType":3}},{"v":"http/IncomingMessage"},{"v":"@proteinjs/server/ExtendedSocket","value":{"packageName":"@proteinjs/server","name":"ExtendedSocket","filePath":"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts","qualifiedName":"@proteinjs/server/ExtendedSocket","properties":[{"name":"request","type":{"packageName":"@proteinjs/server","name":"ExtendedIncomingMessage","filePath":null,"qualifiedName":"@proteinjs/server/ExtendedIncomingMessage","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParents":[{"packageName":"socket.io","name":"Socket","filePath":null,"qualifiedName":"socket.io/Socket","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"sourceType":3}},{"v":"socket.io/Socket"},{"v":"@proteinjs/server/environmentCache","value":{"packageName":"@proteinjs/server","name":"environmentCache","filePath":"/home/runner/work/server/server/packages/server/src/envCache.ts","qualifiedName":"@proteinjs/server/environmentCache","type":{"packageName":"","name":"GlobalDataCache<Env>","filePath":null,"qualifiedName":"/GlobalDataCache<Env>","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"GlobalDataCache","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalDataCache","typeParameters":["@proteinjs/server-api/Env"],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/server-api/GlobalDataCache"},{"v":"@proteinjs/server/healthCheck","value":{"packageName":"@proteinjs/server","name":"healthCheck","filePath":"/home/runner/work/server/server/packages/server/src/routes/healthCheck.ts","qualifiedName":"@proteinjs/server/healthCheck","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/server-api/Route"}],"edges":[{"v":"@proteinjs/server/NodeGlobalDataStorage","w":"@proteinjs/server-api/GlobalDataStorage","value":"implements interface"},{"v":"@proteinjs/server/NodeSessionDataStorage","w":"@proteinjs/server-api/SessionDataStorage","value":"implements interface"},{"v":"@proteinjs/server/ExtendedIncomingMessage","w":"http/IncomingMessage","value":"extends interface"},{"v":"@proteinjs/server/ExtendedSocket","w":"socket.io/Socket","value":"extends interface"},{"v":"@proteinjs/server/environmentCache","w":"@proteinjs/server-api/GlobalDataCache","value":"has type"},{"v":"@proteinjs/server/healthCheck","w":"@proteinjs/server-api/Route","value":"has type"}]}';
24
+ '{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/server/NodeGlobalDataStorage","value":{"packageName":"@proteinjs/server","name":"NodeGlobalDataStorage","filePath":"/home/runner/work/server/server/packages/server/src/NodeGlobalDataStorage.ts","qualifiedName":"@proteinjs/server/NodeGlobalDataStorage","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"HOOK_INITIALIZED","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"GLOBAL_DATA","type":{"packageName":"@proteinjs/server","name":"{ [id: string]: GlobalData }","filePath":null,"qualifiedName":"@proteinjs/server/{ [id: string]: GlobalData }","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"environment","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"setData","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"data","type":{"packageName":"@proteinjs/server-api","name":"GlobalData","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalData","typeParameters":null,"directParents":null}}]},{"name":"getData","returnType":{"packageName":"@proteinjs/server-api","name":"GlobalData","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalData","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"initHook","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/server-api","name":"GlobalDataStorage","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalDataStorage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/server-api/GlobalDataStorage"},{"v":"@proteinjs/server/NodeSessionDataStorage","value":{"packageName":"@proteinjs/server","name":"NodeSessionDataStorage","filePath":"/home/runner/work/server/server/packages/server/src/NodeSessionDataStorage.ts","qualifiedName":"@proteinjs/server/NodeSessionDataStorage","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"HOOK_INITIALIZED","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SESSION_DATA","type":{"packageName":"@proteinjs/server","name":"{ [id: string]: SessionData }","filePath":null,"qualifiedName":"@proteinjs/server/{ [id: string]: SessionData }","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"environment","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"setData","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"data","type":{"packageName":"@proteinjs/server-api","name":"SessionData","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionData","typeParameters":null,"directParents":null}}]},{"name":"getData","returnType":{"packageName":"@proteinjs/server-api","name":"SessionData","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionData","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"clearData","returnType":{"packageName":"","name":"void","filePath":null,"qualifiedName":"/void","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"initHook","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/server-api","name":"SessionDataStorage","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionDataStorage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/server-api/SessionDataStorage"},{"v":"@proteinjs/server/ExtendedIncomingMessage","value":{"packageName":"@proteinjs/server","name":"ExtendedIncomingMessage","filePath":"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts","qualifiedName":"@proteinjs/server/ExtendedIncomingMessage","properties":[{"name":"sessionID","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"user","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParents":[{"packageName":"http","name":"IncomingMessage","filePath":null,"qualifiedName":"http/IncomingMessage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"sourceType":3}},{"v":"http/IncomingMessage"},{"v":"@proteinjs/server/ExtendedSocket","value":{"packageName":"@proteinjs/server","name":"ExtendedSocket","filePath":"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts","qualifiedName":"@proteinjs/server/ExtendedSocket","properties":[{"name":"request","type":{"packageName":"@proteinjs/server","name":"ExtendedIncomingMessage","filePath":null,"qualifiedName":"@proteinjs/server/ExtendedIncomingMessage","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParents":[{"packageName":"socket.io","name":"Socket","filePath":null,"qualifiedName":"socket.io/Socket","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"sourceType":3}},{"v":"socket.io/Socket"},{"v":"@proteinjs/server/environmentCache","value":{"packageName":"@proteinjs/server","name":"environmentCache","filePath":"/home/runner/work/server/server/packages/server/src/envCache.ts","qualifiedName":"@proteinjs/server/environmentCache","type":{"packageName":"","name":"GlobalDataCache<Env>","filePath":null,"qualifiedName":"/GlobalDataCache<Env>","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"GlobalDataCache","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalDataCache","typeParameters":["@proteinjs/server-api/Env"],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/server-api/GlobalDataCache"},{"v":"@proteinjs/server/healthCheck","value":{"packageName":"@proteinjs/server","name":"healthCheck","filePath":"/home/runner/work/server/server/packages/server/src/routes/healthCheck.ts","qualifiedName":"@proteinjs/server/healthCheck","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/server-api/Route"}],"edges":[{"v":"@proteinjs/server/NodeGlobalDataStorage","w":"@proteinjs/server-api/GlobalDataStorage","value":"implements interface"},{"v":"@proteinjs/server/NodeSessionDataStorage","w":"@proteinjs/server-api/SessionDataStorage","value":"implements interface"},{"v":"@proteinjs/server/ExtendedIncomingMessage","w":"http/IncomingMessage","value":"extends interface"},{"v":"@proteinjs/server/ExtendedSocket","w":"socket.io/Socket","value":"extends interface"},{"v":"@proteinjs/server/environmentCache","w":"@proteinjs/server-api/GlobalDataCache","value":"has type"},{"v":"@proteinjs/server/healthCheck","w":"@proteinjs/server-api/Route","value":"has type"}]}';
25
25
 
26
26
  /** Generate Source Links */
27
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/server",
3
- "version": "3.5.1",
3
+ "version": "3.5.3",
4
4
  "description": "A server impl",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -25,7 +25,7 @@
25
25
  "@proteinjs/event": "^1.0.18",
26
26
  "@proteinjs/logger": "^1.0.21",
27
27
  "@proteinjs/reflection": "^1.1.12",
28
- "@proteinjs/server-api": "^3.1.1",
28
+ "@proteinjs/server-api": "^3.1.2",
29
29
  "@proteinjs/util-node": "^1.10.1",
30
30
  "body-parser": "1.19.0",
31
31
  "cookie-parser": "1.4.5",
@@ -64,5 +64,5 @@
64
64
  },
65
65
  "main": "./dist/generated/index.js",
66
66
  "types": "./dist/generated/index.d.ts",
67
- "gitHead": "8fb8f61e0d710d6cfbb74676735a726ec4107219"
67
+ "gitHead": "10387d6d8f4af3b4f6d6a320741504e1ce5d1bdb"
68
68
  }
@@ -26,6 +26,24 @@ export class NodeSessionDataStorage implements SessionDataStorage {
26
26
  return NodeSessionDataStorage.SESSION_DATA[asyncHooks.executionAsyncId()];
27
27
  }
28
28
 
29
+ /**
30
+ * Drop the CURRENT async id's entry so the next `setData` seeds fresh. The init hook copies
31
+ * a populated bag onto every descendant async resource and `setData` is first-write-wins, so
32
+ * a request dispatched inside a PREVIOUS request's lineage (keep-alive socket reuse — the
33
+ * normal case under a 620s keepAliveTimeout) would otherwise run as the prior request's user
34
+ * (observed 2026-08-26: /dev/login account switch, home greeting server-rendered with the
35
+ * previous account's name). Scoped to the current id on purpose: in-flight hops of the
36
+ * previous request keep their own already-copied entries, and descendants created after the
37
+ * re-seed inherit the fresh bag.
38
+ */
39
+ clearData(): void {
40
+ if (!NodeSessionDataStorage.HOOK_INITIALIZED) {
41
+ this.initHook();
42
+ }
43
+
44
+ delete NodeSessionDataStorage.SESSION_DATA[asyncHooks.executionAsyncId()];
45
+ }
46
+
29
47
  private initHook() {
30
48
  asyncHooks
31
49
  .createHook({
package/src/loadRoutes.ts CHANGED
@@ -87,6 +87,13 @@ function wrapRoute(
87
87
  for (const sessionDataCache of getSessionDataCaches()) {
88
88
  sessionData.data[sessionDataCache.key] = await sessionDataCache.create(sessionData.sessionId, sessionData.user);
89
89
  }
90
+ // A request always seeds ITS OWN session context: on a reused keep-alive socket this
91
+ // dispatch is born inside the previous request's async lineage (the storage's init hook
92
+ // copies bags onto descendants), and first-write-wins setData would silently drop this
93
+ // request's seed — the request then runs (and server-renders proteinjs.sessionData) as
94
+ // the PRIOR request's user (observed 2026-08-26: stale home greeting after a /dev/login
95
+ // account switch; roster correct, greeting wrong). Clear the inherited entry first.
96
+ Session.clearData();
90
97
  Session.setData(sessionData);
91
98
 
92
99
  if (shouldLogRequest(request, config)) {
@@ -24,6 +24,13 @@ export const createReactApp = (serverConfig: ServerConfig) => {
24
24
  }
25
25
 
26
26
  const helmet = ReactHelmet.renderStatic();
27
+ // The page must ALWAYS revalidate (found live 2026-09-01, the mobile-app stale-page
28
+ // investigation): without an explicit policy, HTTP heuristic caching applies (RFC 9111
29
+ // §4.2.2) — WKWebView in particular can serve the cached page without revalidating,
30
+ // across app force-quits, pinning stale bundle POINTERS long after a deploy. The hashed
31
+ // bundles under /static keep their long cache (a fresh page always points at fresh
32
+ // hashes); `no-cache` + the ETag express already stamps = a cheap 304 on every load.
33
+ response.set('Cache-Control', 'no-cache');
27
34
  response.send(`<!DOCTYPE html>
28
35
  <html ${helmet.htmlAttributes}>
29
36
  <head>
@@ -54,6 +54,10 @@ startServer({
54
54
  response.status(200).send('slow-done');
55
55
  },
56
56
  },
57
+ // A bundle pointer so the '*' react-app route serves its HTML — the html-cache-control
58
+ // suite asserts response headers on the page the app actually ships. No staticContentDir:
59
+ // nothing needs the bundle to resolve, only the page response to render.
60
+ staticContent: { bundlePaths: ['bundles/app.test.js'] },
57
61
  shutdown: {
58
62
  drainDelayMs: process.env.FIXTURE_DRAIN_DELAY_MS ? Number(process.env.FIXTURE_DRAIN_DELAY_MS) : undefined,
59
63
  drainTimeoutMs: process.env.FIXTURE_DRAIN_TIMEOUT_MS ? Number(process.env.FIXTURE_DRAIN_TIMEOUT_MS) : undefined,
@@ -0,0 +1,129 @@
1
+ import * as http from 'http';
2
+ import * as net from 'net';
3
+ import * as path from 'path';
4
+ import { ChildProcess, spawn } from 'child_process';
5
+
6
+ /**
7
+ * HTML cache policy of a real server process (spawns the built dist — run `npm run build`
8
+ * first), asserted through the front door on the page the react-app route actually sends.
9
+ *
10
+ * THE CLASS THIS PINS (found live 2026-09-01, the mobile-app stale-page investigation): the
11
+ * HTML response carried NO Cache-Control header — an ETag only. With no explicit policy,
12
+ * HTTP heuristic caching applies (RFC 9111 §4.2.2), and WKWebView in particular can serve
13
+ * the cached page without revalidating — across app force-quits — pinning stale bundle
14
+ * POINTERS long after a deploy. The hashed bundles under /static keep their long cache (a
15
+ * new page always points at new hashes); the PAGE must always revalidate. `no-cache` states
16
+ * exactly that, and the ETag the response already carries keeps revalidation a cheap 304.
17
+ */
18
+ const packageRoot = path.join(__dirname, '..');
19
+ const fixturePath = path.join(__dirname, 'fixture', 'gracefulShutdownServer.js');
20
+
21
+ describe('html cache policy', () => {
22
+ let fixture: Fixture | undefined;
23
+
24
+ afterEach(async () => {
25
+ if (fixture && fixture.child.exitCode === null && fixture.child.signalCode === null) {
26
+ fixture.child.kill('SIGKILL');
27
+ await fixture.exited.catch(() => undefined);
28
+ }
29
+ fixture = undefined;
30
+ });
31
+
32
+ it('the react-app HTML response says Cache-Control: no-cache — the page always revalidates', async () => {
33
+ fixture = await startFixture();
34
+
35
+ const result = await request(fixture.port, '/');
36
+ expect(result.status).toBe(200);
37
+ // Sanity: this IS the react-app page (the configured bundle pointer is in the body).
38
+ expect(result.body).toContain('bundles/app.test.js');
39
+ expect(result.headers['content-type']).toContain('text/html');
40
+ expect(result.headers['cache-control']).toBe('no-cache');
41
+ }, 30000);
42
+
43
+ it('every page path rides the same policy (the catch-all route is the one HTML owner)', async () => {
44
+ fixture = await startFixture();
45
+
46
+ const result = await request(fixture.port, '/chat');
47
+ expect(result.status).toBe(200);
48
+ expect(result.headers['content-type']).toContain('text/html');
49
+ expect(result.headers['cache-control']).toBe('no-cache');
50
+ }, 30000);
51
+ });
52
+
53
+ type Fixture = {
54
+ child: ChildProcess;
55
+ port: number;
56
+ exited: Promise<{ code: number | null; signal: NodeJS.Signals | null }>;
57
+ };
58
+
59
+ async function startFixture(): Promise<Fixture> {
60
+ const port = await ephemeralPort();
61
+ // Scrub the env vars startServer reads (dev machines export some of these): the fixture's
62
+ // behavior must come from its own config only.
63
+ const env = { ...process.env };
64
+ delete env.SERVER_PORT;
65
+ delete env.DEVELOPMENT;
66
+ delete env.DISABLE_HOT_CLIENT_BUILDS;
67
+ delete env.HMR_PORT;
68
+ const child = spawn(process.execPath, [fixturePath], {
69
+ cwd: packageRoot,
70
+ env: { ...env, FIXTURE_PORT: String(port) },
71
+ stdio: ['ignore', 'pipe', 'pipe'],
72
+ });
73
+ let output = '';
74
+ child.stdout!.on('data', (chunk) => (output += String(chunk)));
75
+ child.stderr!.on('data', (chunk) => (output += String(chunk)));
76
+ const exited = new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolve) =>
77
+ child.once('exit', (code, signal) => resolve({ code, signal }))
78
+ );
79
+ // Ready = the health check answers 200 (readiness through the front door, not log lines).
80
+ const deadline = Date.now() + 20000;
81
+ for (;;) {
82
+ if (child.exitCode !== null || child.signalCode !== null) {
83
+ throw new Error(`Fixture exited during boot; output:\n${output}`);
84
+ }
85
+ const result = await request(port, '/health-check').catch(() => undefined);
86
+ if (result?.status === 200) {
87
+ return { child, port, exited };
88
+ }
89
+ if (Date.now() > deadline) {
90
+ throw new Error(`Fixture never became ready; output:\n${output}`);
91
+ }
92
+ await sleep(100);
93
+ }
94
+ }
95
+
96
+ /** One request on its OWN connection (agent: false — no keep-alive pooling). The forwarded
97
+ * proto is the LB topology in miniature: the prod shape 302s plain http to https. */
98
+ function request(
99
+ port: number,
100
+ requestPath: string
101
+ ): Promise<{ status: number; body: string; headers: http.IncomingHttpHeaders }> {
102
+ return new Promise((resolve, reject) => {
103
+ const req = http.get(
104
+ { host: '127.0.0.1', port, path: requestPath, agent: false, headers: { 'X-Forwarded-Proto': 'https' } },
105
+ (res) => {
106
+ let body = '';
107
+ res.on('data', (chunk) => (body += String(chunk)));
108
+ res.on('end', () => resolve({ status: res.statusCode ?? 0, body, headers: res.headers }));
109
+ res.on('error', reject);
110
+ }
111
+ );
112
+ req.on('error', reject);
113
+ });
114
+ }
115
+
116
+ async function ephemeralPort(): Promise<number> {
117
+ return new Promise((resolve, reject) => {
118
+ const probe = net.createServer();
119
+ probe.once('error', reject);
120
+ probe.listen(0, '127.0.0.1', () => {
121
+ const address = probe.address() as net.AddressInfo;
122
+ probe.close(() => resolve(address.port));
123
+ });
124
+ });
125
+ }
126
+
127
+ function sleep(ms: number): Promise<void> {
128
+ return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
129
+ }
@@ -0,0 +1,51 @@
1
+ import { SessionData } from '@proteinjs/server-api';
2
+ import { NodeSessionDataStorage } from '../src/NodeSessionDataStorage';
3
+
4
+ /**
5
+ * The keep-alive session-bleed class (observed 2026-08-26: after a /dev/login account
6
+ * switch, the home page server-rendered the PREVIOUS account's display name — roster
7
+ * correct, greeting wrong). Mechanism: the storage's init hook copies a populated bag onto
8
+ * every descendant async resource, `setData` is first-write-wins, and a request dispatched
9
+ * on a reused keep-alive socket is born inside the previous request's lineage — so the new
10
+ * request's seed silently loses and the request runs as the prior request's user.
11
+ *
12
+ * These tests pin the hazard AND the request-boundary cure `wrapRoute` now applies:
13
+ * `clearData()` before the seed makes the request's own `setData` authoritative.
14
+ */
15
+ describe('session data at the request boundary', () => {
16
+ const storage = new NodeSessionDataStorage();
17
+ const asData = (user: string): SessionData => ({ sessionId: `session-${user}`, user, data: {} });
18
+
19
+ /** A continuation born INSIDE the current async context — the keep-alive shape: request B's
20
+ * dispatch created while request A's lineage still tags the trigger ids. */
21
+ const bornInLineage = (run: () => void): Promise<void> =>
22
+ new Promise((resolve, reject) => {
23
+ setImmediate(() => {
24
+ try {
25
+ run();
26
+ resolve();
27
+ } catch (e) {
28
+ reject(e);
29
+ }
30
+ });
31
+ });
32
+
33
+ it('pins the hazard: a dispatch born in a prior lineage INHERITS the bag, and a bare re-seed silently loses', async () => {
34
+ storage.setData(asData('account-a'));
35
+ await bornInLineage(() => {
36
+ expect(storage.getData()?.user).toBe('account-a'); // inherited from the trigger lineage
37
+ storage.setData(asData('account-b')); // first-write-wins: this seed is DROPPED
38
+ expect(storage.getData()?.user).toBe('account-a'); // the silent bleed
39
+ });
40
+ });
41
+
42
+ it('the request-boundary cure: clearData() then setData makes the new request authoritative', async () => {
43
+ storage.setData(asData('account-a'));
44
+ await bornInLineage(() => {
45
+ // What wrapRoute does per request now: clear the inherited entry, then seed.
46
+ storage.clearData();
47
+ storage.setData(asData('account-b'));
48
+ expect(storage.getData()?.user).toBe('account-b');
49
+ });
50
+ });
51
+ });