The re-review closed all six earlier findings but surfaced the same bug class
one level over: the memo key carried the scope but not the subject, so
reassigning ctx.user mid-request served the previous principal's verdict.
Demonstrated - u1 allowed, then ctx.user = u2 still returned true, and
clearing ctx.user entirely revoked nothing. Triggered by impersonation or
"view as user" middleware, step-up auth, session revocation mid-request, or
simply registering an auth middleware after authzMiddleware.
Also: symbols now memo by identity (String() collapsed two distinct symbols
sharing a description into one slot), -0 stays distinct from 0, the
rejected-redirect log no longer echoes CR/LF verbatim into the log stream,
and a non-ASCII redirect target is encodeURI'd rather than throwing out of
the Response constructor and 500ing on a denial path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>