Skip to content

WIP: Various updates for AI review - #646

Merged
leoisadev1 merged 2 commits into
mainfrom
ai-review-workflow-20260213-211348
Feb 14, 2026
Merged

WIP: Various updates for AI review#646
leoisadev1 merged 2 commits into
mainfrom
ai-review-workflow-20260213-211348

Conversation

@leoisadev1

@leoisadev1 leoisadev1 commented Feb 14, 2026

Copy link
Copy Markdown
Member

Automated PR for AI review (Greptile/Cubic)


Summary by cubic

Aligns benchmark import with live OpenRouter models, improve model matching, and polish the model selector/info UI. Server-hydrated auth now avoids loading flashes with a timeout and stricter loading guard.

  • New Features

    • Server: fetches OpenRouter model IDs and builds AA→OpenRouter mapping from live data with expanded manual overrides.
    • Web: refreshed Model Selector and Info Panel with compact badges (Vision/Reasoning/Tool Calling), desktop hover preview panel, better keyboard nav/positioning, and thin scrollbars; improved tooltips with flexible positioning and a single provider; cleaner circular progress text.
    • Auth: preloads the user on the server and passes it to the client; adds a 3s session fetch timeout and keeps loading until it completes to prevent flicker.
  • Bug Fixes

    • Correct AA evaluation keys when storing benchmarks (artificial_analysis_coding_index, artificial_analysis_math_index).
    • Remove hardcoded POPULAR_MODEL_IDS; only match against available OpenRouter IDs.
    • UI polish: proper progress text color, updated benchmark color thresholds, tooltip z-index control, and reduced tooltip provider re-renders.

Written for commit 6d1f407. Summary will update on new commits.

@railway-app
railway-app Bot temporarily deployed to OpenChat / openchat-pr-646 February 14, 2026 02:14 Destroyed
@railway-app

railway-app Bot commented Feb 14, 2026

Copy link
Copy Markdown

🚅 Deployed to the openchat-pr-646 environment in OpenChat

Service Status Web Updated (UTC)
web ✅ Success (View Logs) Web Feb 14, 2026 at 2:25 am

@tembo

tembo Bot commented Feb 14, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security Issues Found

Severity Vulnerability Type File Line(s)
Medium Session Token Storage Regression (XSS attack surface) apps/web/src/lib/auth-client.tsx 29-32

Medium: Session Token Storage Regression — apps/web/src/lib/auth-client.tsx

What changed: The custom inMemoryStorage adapter for crossDomainClient() was removed, reverting to the plugin's default storage (which uses localStorage). The previous implementation explicitly kept session tokens in memory only to reduce XSS token theft risk.

Previous (secure) code:

crossDomainClient({
  storage: inMemoryStorage,
  disableCache: true,
}),

New code:

crossDomainClient(),

Why this matters: With the default storage, crossDomainClient will persist session-related tokens in localStorage. If any XSS vulnerability is introduced anywhere in the application, an attacker can trivially read localStorage to exfiltrate these tokens. The previous in-memory-only approach eliminated this persistence, narrowing the attack surface. While the primary session is maintained via HttpOnly cookies (which remain safe from JS access), the cross-domain tokens stored in localStorage could be used to establish sessions on other domains or replay auth flows.

Recommended fix: If the inMemoryStorage was removed to fix the infinite loop issue, consider keeping a storage adapter that doesn't persist to localStorage while also incorporating the new server-side session hydration (initialUser). For example:

const inMemoryStorage = {
  _store: new Map<string, string>(),
  setItem: (key: string, value: string) => {
    if (inMemoryStorage._store.get(key) === value) return;
    inMemoryStorage._store.set(key, value);
  },
  getItem: (key: string) => inMemoryStorage._store.get(key) ?? null,
  removeItem: (key: string) => { inMemoryStorage._store.delete(key); },
};

// Then use:
crossDomainClient({
  storage: inMemoryStorage,
}),

This preserves the XSS-hardening benefit while still allowing the new initialUser server-side hydration to work (since that flows through StableAuthProvider, not through crossDomainClient's storage).


Summary: 1 medium severity finding.

Scanned commit: c363ebc

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 14 files

Confidence score: 3/5

  • Potential auth state ambiguity in apps/web/src/lib/auth-client.tsx: isAuthenticated can be true while session is null with loading false, which could mislead consumers into treating users as fully authenticated
  • Route blocking risk in apps/web/src/routes/__root.tsx since the session fetch has no timeout in beforeLoad, so a slow auth service could hang page rendering
  • Pay close attention to apps/web/src/lib/auth-client.tsx and apps/web/src/routes/__root.tsx - partially initialized auth state and blocking session fetch behavior.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/web/src/styles.css">

<violation number="1" location="apps/web/src/styles.css:184">
P2: Hardcoded `oklch` color values don't follow the project's theming pattern. The rest of the file uses CSS custom properties (e.g., `var(--muted-foreground)`) that adapt to dark/light mode. Consider using theme variables so the scrollbar appearance is consistent across themes.

For example, you could use `color-mix` or define dedicated scrollbar color variables in `:root` and `.dark`.</violation>
</file>

<file name="apps/web/src/components/model-selector.tsx">

<violation number="1" location="apps/web/src/components/model-selector.tsx:240">
P2: `TooltipProvider` is instantiated inside each `ModelItem`, creating a new context provider per list item. Since `ModelItem` is rendered for every model in the list, this creates N provider instances. Move the `TooltipProvider` out of `ModelItem` and wrap the entire list (or the `ModelSelector` component) with a single `TooltipProvider` instead.</violation>
</file>

<file name="apps/web/src/lib/benchmark-formatting.ts">

<violation number="1" location="apps/web/src/lib/benchmark-formatting.ts:41">
P2: JSDoc comment is stale: it still documents the old thresholds (≥70, 40-69, <40) and color name (red) but the code now uses ≥30, 15-29, <15 and rose. Update the comment to match the new logic.</violation>
</file>

<file name="apps/web/src/routes/__root.tsx">

<violation number="1" location="apps/web/src/routes/__root.tsx:34">
P2: The `fetch` to the auth session endpoint has no timeout. Since this runs in `beforeLoad` (which blocks route rendering), a slow or unresponsive auth service will cause the entire page load to hang. Consider adding an `AbortSignal.timeout()` to bound the wait time.</violation>
</file>

<file name="apps/web/src/components/model-info-panel.tsx">

<violation number="1" location="apps/web/src/components/model-info-panel.tsx:235">
P2: Hardcoded `"OpenRouter"` replaces dynamic `{model.provider}`. This field will always show the same value regardless of the actual model provider, making it redundant and uninformative. If the intent is to distinguish API provider from developer, consider using a constant or deriving this from configuration rather than a hardcoded string.</violation>
</file>

<file name="apps/web/src/lib/auth-client.tsx">

<violation number="1" location="apps/web/src/lib/auth-client.tsx:89">
P1: `isAuthenticated` is `true` while `session` is `null` when `initialUser` is provided. Since `loading` is also `false`, consumers have no way to distinguish this partially-initialized state from a fully authenticated one. Any code that accesses `session.id` or `session.token` after checking `isAuthenticated && !loading` will throw a null reference error. Consider keeping `loading: true` until `fetchSession` completes, or documenting that `session` may be null even when authenticated.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread apps/web/src/lib/auth-client.tsx Outdated
Comment thread apps/web/src/styles.css Outdated
Comment thread apps/web/src/components/model-selector.tsx Outdated
Comment thread apps/web/src/lib/benchmark-formatting.ts
Comment thread apps/web/src/routes/__root.tsx
<span className="text-muted-foreground">Provider</span>
<p className="font-medium text-foreground">{model.provider}</p>
<span className="text-[11px] text-muted-foreground">Provider</span>
<p className="text-xs font-medium text-foreground">OpenRouter</p>

@cubic-dev-ai cubic-dev-ai Bot Feb 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Hardcoded "OpenRouter" replaces dynamic {model.provider}. This field will always show the same value regardless of the actual model provider, making it redundant and uninformative. If the intent is to distinguish API provider from developer, consider using a constant or deriving this from configuration rather than a hardcoded string.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/src/components/model-info-panel.tsx, line 235:

<comment>Hardcoded `"OpenRouter"` replaces dynamic `{model.provider}`. This field will always show the same value regardless of the actual model provider, making it redundant and uninformative. If the intent is to distinguish API provider from developer, consider using a constant or deriving this from configuration rather than a hardcoded string.</comment>

<file context>
@@ -176,89 +182,83 @@ export function ModelInfoPanel({ model, className }: ModelInfoPanelProps) {
-					<span className="text-muted-foreground">Provider</span>
-					<p className="font-medium text-foreground">{model.provider}</p>
+					<span className="text-[11px] text-muted-foreground">Provider</span>
+					<p className="text-xs font-medium text-foreground">OpenRouter</p>
 				</div>
 				<div>
</file context>
Suggested change
<p className="text-xs font-medium text-foreground">OpenRouter</p>
<p className="text-xs font-medium text-foreground">{model.provider}</p>
Fix with Cubic

- auth-client: keep loading=true until fetchSession completes
- benchmark-formatting: update stale JSDoc comment
- __root.tsx: add timeout to auth fetch (3s)
- styles.css: use theme variables for scrollbar colors
- model-selector: hoist TooltipProvider outside ModelItem loop
@railway-app
railway-app Bot temporarily deployed to OpenChat / openchat-pr-646 February 14, 2026 02:23 Destroyed
@tembo

tembo Bot commented Feb 14, 2026

Copy link
Copy Markdown
Contributor

✅ No security issues found — scanned commits: c363ebc, 6d1f407

@leoisadev1
leoisadev1 merged commit 70b9b4d into main Feb 14, 2026
7 of 8 checks passed
@leoisadev1
leoisadev1 deleted the ai-review-workflow-20260213-211348 branch February 14, 2026 02:26

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/web/src/lib/auth-client.tsx">

<violation number="1" location="apps/web/src/lib/auth-client.tsx:89">
P1: Setting `loading` to `true` unconditionally defeats the server-side user hydration. When `initialUser` is provided, the user data is already available in `sessionData`, but consumers will still see `loading: true` and show loading indicators until the async `fetchSession` completes — reintroducing the exact loading flash this PR aims to eliminate. The previous logic `useState(!initialUser)` was correct.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

}
return { user: null, session: null };
});
const [loading, setLoading] = useState(true);

@cubic-dev-ai cubic-dev-ai Bot Feb 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Setting loading to true unconditionally defeats the server-side user hydration. When initialUser is provided, the user data is already available in sessionData, but consumers will still see loading: true and show loading indicators until the async fetchSession completes — reintroducing the exact loading flash this PR aims to eliminate. The previous logic useState(!initialUser) was correct.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/src/lib/auth-client.tsx, line 89:

<comment>Setting `loading` to `true` unconditionally defeats the server-side user hydration. When `initialUser` is provided, the user data is already available in `sessionData`, but consumers will still see `loading: true` and show loading indicators until the async `fetchSession` completes — reintroducing the exact loading flash this PR aims to eliminate. The previous logic `useState(!initialUser)` was correct.</comment>

<file context>
@@ -86,7 +86,7 @@ export function StableAuthProvider({
     return { user: null, session: null };
   });
-  const [loading, setLoading] = useState(!initialUser);
+  const [loading, setLoading] = useState(true);
   const fetchedRef = useRef(false);
   const fetchingRef = useRef(false);
</file context>
Suggested change
const [loading, setLoading] = useState(true);
const [loading, setLoading] = useState(!initialUser);
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant