Skip to content

Commit b080dcd

Browse files
Enalmadaclaude
andcommitted
fix: address PR #40 review feedback (middleware leak + TSS-7 robustness)
- src/server/access/middleware.ts (HIGH): move setResponseStatus + logger into dynamic imports inside the .server() body. middleware.ts is reachable from start.ts, so top-level imports of @tanstack/react-start/server and ~/utils/logger (which pulls Axiom) would leak server-only code into the client bundle — exactly the TSS-2 class this initiative targets, and a violation of our own SKILL.md dynamic-import rule. logger.info/error are module-scope closures (no `this`), so the destructure-to-logFn stays safe. - scripts/check-tss-7.sh (MEDIUM x3): - is_exempt now uses leading-`*` glob so ./-prefixed $CHANGED paths (git diff --name-only) still match the exemptions. - getRequest regex tolerates whitespace: `getRequest ()`, `getRequest( )`. - auth.api.getSession regex tolerates whitespace: `getSession (`. Verified: whitespace-variant fixtures now caught; ./-prefixed exempt paths still skipped; check-types + biome + 62 unit tests green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent d385543 commit b080dcd

2 files changed

Lines changed: 20 additions & 12 deletions

File tree

scripts/check-tss-7.sh

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,16 @@ fi
4848
# Helper modules + test setup are by design exempt — they ARE the
4949
# canonical helpers, or they configure the global test mock.
5050
is_exempt() {
51+
# Leading `*` so `./src/...`-prefixed paths (e.g. from `git diff
52+
# --name-only` in $CHANGED diff-mode) still match the exemptions.
5153
case "$1" in
52-
src/server/auth/request.ts) return 0 ;;
53-
src/server/auth/session.ts) return 0 ;;
54-
src/server/auth/auth.ts) return 0 ;;
55-
src/test/setup.ts) return 0 ;;
56-
src/utils/test/playwright.ts) return 0 ;;
54+
*src/server/auth/request.ts) return 0 ;;
55+
*src/server/auth/session.ts) return 0 ;;
56+
*src/server/auth/auth.ts) return 0 ;;
57+
*src/test/setup.ts) return 0 ;;
58+
*src/utils/test/playwright.ts) return 0 ;;
5759
# Better Auth route handler — different dispatch path
58-
src/routes/api/*) return 0 ;;
60+
*src/routes/api/*) return 0 ;;
5961
esac
6062
return 1
6163
}
@@ -70,8 +72,9 @@ for f in $files; do
7072
# typically JSDoc rationale that explicitly mentions the bypassed call
7173
# while explaining why the helper exists.
7274
#
73-
# Bare getRequest() — allow getSessionRequest references via grep -v
74-
bare=$(grep -nE 'getRequest\(\)' "$f" 2>/dev/null \
75+
# Bare getRequest() — allow getSessionRequest references via grep -v.
76+
# Tolerate whitespace variants: `getRequest ()`, `getRequest( )`.
77+
bare=$(grep -nE 'getRequest[[:space:]]*\([[:space:]]*\)' "$f" 2>/dev/null \
7578
| grep -vE '^[0-9]+:[[:space:]]*(//|\*|/\*)' \
7679
| grep -v 'getSessionRequest' \
7780
|| true)
@@ -81,8 +84,8 @@ for f in $files; do
8184
printf '%s\n' "$bare" | sed 's/^/ /'
8285
fi
8386

84-
# Direct auth.api.getSession( call
85-
direct=$(grep -nE 'auth\.api\.getSession\(' "$f" 2>/dev/null \
87+
# Direct auth.api.getSession( call. Tolerate whitespace: `getSession (`.
88+
direct=$(grep -nE 'auth\.api\.getSession[[:space:]]*\(' "$f" 2>/dev/null \
8689
| grep -vE '^[0-9]+:[[:space:]]*(//|\*|/\*)' \
8790
|| true)
8891
if [ -n "$direct" ]; then

src/server/access/middleware.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,22 @@
1313
*/
1414

1515
import { createMiddleware } from "@tanstack/react-start";
16-
import { setResponseStatus } from "@tanstack/react-start/server";
17-
import { logger } from "~/utils/logger";
1816
import { hasHttpErrorHints } from "./http-errors";
1917

2018
export const authErrorTranslator = createMiddleware({ type: "function" }).server(async ({ next }) => {
2119
try {
2220
return await next();
2321
} catch (err) {
2422
if (hasHttpErrorHints(err)) {
23+
// Dynamic imports: middleware.ts is reachable from start.ts, so
24+
// top-level imports of `@tanstack/react-start/server` and
25+
// `~/utils/logger` (which pulls in Axiom) would leak server-only
26+
// code into the client bundle (TSS-2). Load them inside the
27+
// server-only `.server()` body instead.
28+
const { setResponseStatus } = await import("@tanstack/react-start/server");
2529
setResponseStatus(err.httpStatus);
2630
// Log server-side for Axiom correlation (4xx info, 5xx error).
31+
const { logger } = await import("~/utils/logger");
2732
const logFn = err.httpStatus >= 500 ? logger.error : logger.info;
2833
logFn(`[authErrorTranslator] ${err.name}`, {
2934
message: err.message,

0 commit comments

Comments
 (0)