This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch feature/WW-3576-session-map-staleness
in repository https://gitbox.apache.org/repos/asf/struts.git

commit fb355c30c9ad4fca12d7c14e782a3631f2982db7
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sun Oct 18 12:50:29 2026 +0200

    WW-3576 docs: tighten the detach rationale wording
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../specs/2026-10-18-WW-3576-session-map-staleness-design.md       | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git 
a/docs/superpowers/specs/2026-10-18-WW-3576-session-map-staleness-design.md 
b/docs/superpowers/specs/2026-10-18-WW-3576-session-map-staleness-design.md
index 07c8654cf..08dadb2fd 100644
--- a/docs/superpowers/specs/2026-10-18-WW-3576-session-map-staleness-design.md
+++ b/docs/superpowers/specs/2026-10-18-WW-3576-session-map-staleness-design.md
@@ -57,7 +57,7 @@ when that session dies (request threads), and one map that is 
stale *by design*
 - **Pins the session it first sees (decided)**, as today: 
`request.getSession(false)` at construction,
   `request.getSession(true)` on the first `put` when none is pinned. It does 
**not** re-resolve through
   the request on every call — code holding the map past its request 
(async-plugin `Callable`s, stored
-  `SessionAware` fields) must never resolve through a recycled request, which 
may be another user's.
+  `SessionAware` fields) must never resolve a session through a request that 
has already ended.
 - **Invalidation is detected, not hidden:** an `IllegalStateException` from 
the pinned session means it
   was invalidated (by another request or directly); the map un-pins it and 
answers as "no session"
   (`null` / `false` / empty set / no-op). A later `put` obtains a session 
through
@@ -70,9 +70,8 @@ when that session dies (request threads), and one map that is 
stale *by design*
   async dispatch's cleanup. A detached map never calls its request again: with 
a live pinned session it
   keeps working (async `Callable`s, stored `SessionAware` fields); a `put` 
with no live pinned session
   throws `IllegalStateException`. Reason: a background thread (sandbox escape, 
custom
-  `BackgroundProcess`) reaching `request.getSession(true)` after the request 
was recycled would write
-  into another user's session. This also closes the same path for a 
never-pinned map used after its
-  request ended, which predates this change. Detach is package-private.
+  `BackgroundProcess`) must not resolve a session through a request that has 
already ended; this applies
+  equally to a never-pinned map used after its request ended. Detach is 
package-private.
 - The pinned reference is read once per call into a local (no 
check-then-reread), so a concurrent
   `invalidate()` on the same map cannot NPE; how it is published (`volatile`) 
is the builder's.
 - **No `entries` cache:** `entrySet()` is built fresh on every call; an 
entry's `setValue` writes

Reply via email to