Skip to content

agent: @U0AJM7X8FBR Admin Codebase - Hide Sensitive Info Toggle • actual: email#17

Merged
recoup-coding-agent merged 10 commits intomainfrom
agent/-u0ajm7x8fbr-admin-codebase----1773838355918
Mar 18, 2026
Merged

agent: @U0AJM7X8FBR Admin Codebase - Hide Sensitive Info Toggle • actual: email#17
recoup-coding-agent merged 10 commits intomainfrom
agent/-u0ajm7x8fbr-admin-codebase----1773838355918

Conversation

@sweetmantech
Copy link
Copy Markdown
Contributor

@sweetmantech sweetmantech commented Mar 18, 2026

Automated PR from coding agent.

Summary by CodeRabbit

  • New Features

    • Added a toggle to mask sensitive email information across the application for enhanced privacy.
    • Introduced a new application header displaying "Recoup Admin" with user login and hide controls.
  • UI Improvements

    • Refined home page layout for improved visual clarity.
    • Enhanced table cells with dedicated components for consistent email and timestamp rendering.

Adds a global Eye/EyeOff toggle button (fixed top-right) that masks all
email fields across the admin dashboard when activated.

- New HideProvider context + useHide hook
- New maskEmail utility (e.g. "jo***@ex***.com")
- HideToggle component wired into global Providers
- privyLoginsColumns, sandboxesColumns, AccountReposList all respect isHidden

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
admin Ready Ready Preview Mar 18, 2026 4:21pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces a new client-side hide/masking feature with context-based infrastructure, creates dedicated UI components for email display with optional masking, refactors table columns to use component-based cells, updates the app layout with a header component, and reorganizes import paths for better module structure.

Changes

Cohort / File(s) Summary
Hide/Masking Infrastructure
lib/hide/maskEmail.ts, lib/hide/useDisplayEmail.ts, providers/HideProvider.tsx
New utility for email masking with specific patterns; client hook for display-safe email that checks hide context state; React context provider managing hidden state with toggle function.
Header & Navigation Components
components/Header/AppHeader.tsx, components/Header/HideToggle.tsx
New header bar component displaying "Recoup Admin" title with LoginButton and hide toggle controls; new toggle button component consuming HideContext to switch between Eye/EyeOff icons and update aria attributes.
Email Display Cell Components
components/PrivyLogins/EmailCell.tsx, components/PrivyLogins/LastSeenCell.tsx, components/Sandboxes/AccountEmailCell.tsx, components/SandboxOrgs/AccountRepoLink.tsx
New dedicated cell/link components for rendering email, last-seen timestamp, and account links with masking support; replaces inline rendering logic from tables.
Table Column Refactoring
components/PrivyLogins/privyLoginsColumns.tsx, components/Sandboxes/sandboxesColumns.tsx, components/SandboxOrgs/AccountReposList.tsx
Updated table columns to use new EmailCell, LastSeenCell, and AccountEmailCell components; replaced inline Link rendering with dedicated component rendering.
Login & Layout Updates
components/Login/LoginButton.tsx, app/layout.tsx, components/Home/HomePage.tsx, providers/Providers.tsx
Added useDisplayEmail to LoginButton for masked display; wrapped children with new flex layout and AppHeader in app layout; removed header markup from HomePage; wrapped PrivyProvider with HideProvider.
Import Path Reorganization
components/Home/AdminDashboard.tsx, components/PrivyLogins/PrivyLoginsPage.tsx, components/SandboxOrgs/SandboxOrgsPage.tsx, components/Sandboxes/SandboxesPage.tsx
Updated ApiDocsLink import paths from @/components/ApiDocsLink to @/components/ApiDocs/ApiDocsLink.

Sequence Diagram

sequenceDiagram
    participant User
    participant HideToggle
    participant HideContext
    participant Component as Email Component<br/>(e.g., EmailCell)
    participant useDisplayEmail
    participant maskEmail

    User->>HideToggle: Click toggle
    HideToggle->>HideContext: Call toggle()<br/>(flip isHidden)
    HideContext-->>HideToggle: Update isHidden state
    
    Component->>useDisplayEmail: Call useDisplayEmail(email)
    useDisplayEmail->>HideContext: Check isHidden state
    HideContext-->>useDisplayEmail: Return isHidden boolean
    
    alt isHidden = true
        useDisplayEmail->>maskEmail: Call maskEmail(email)
        maskEmail-->>useDisplayEmail: Return masked email
        useDisplayEmail-->>Component: Return masked email
    else isHidden = false
        useDisplayEmail-->>Component: Return original email
    end
    
    Component-->>User: Render email<br/>(masked or original)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A toggle's hop, an email's mask,
Components spring from yesterday's task,
New cells and links now lead the way,
While headers guide and hide at play—
The admin burrow's gleaming new!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.04% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective: adding a 'Hide Sensitive Info' toggle feature focused on masking email display across the admin codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/-u0ajm7x8fbr-admin-codebase----1773838355918
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
providers/HideProvider.tsx (1)

27-29: Consider adding a development-time warning for missing provider.

The current implementation silently falls back to default values when useHide is called outside the provider boundary. This is fine for this feature, but could make debugging harder if a component is accidentally rendered outside the provider.

♻️ Optional: Add development warning
+const HideContext = createContext<HideContextValue | null>(null);
+
 export function useHide() {
-  return useContext(HideContext);
+  const context = useContext(HideContext);
+  if (!context) {
+    if (process.env.NODE_ENV === "development") {
+      console.warn("useHide called outside of HideProvider");
+    }
+    return { isHidden: false, toggle: () => {} };
+  }
+  return context;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@providers/HideProvider.tsx` around lines 27 - 29, The useHide hook should
warn in development when it's used outside the HideContext provider: retrieve
the context with useContext(HideContext) inside useHide, and if
process.env.NODE_ENV !== 'production' and the returned value is undefined (or
equals your default sentinel), call console.warn with a clear message mentioning
useHide and HideContext to help debugging, then return the context value as
before; update the useHide function to perform this check so production behavior
is unchanged but developers get a visible warning when the provider is missing.
components/PrivyLogins/privyLoginsColumns.tsx (1)

21-23: Consider simplifying the cell definition.

The wrapper getValue={() => getValue<string | null>()} is functional but verbose. You could pass getValue directly with a type assertion, or refactor EmailCell to accept the value directly (similar to AccountEmailCell in sandboxesColumns.tsx).

♻️ Optional: Simplify by passing value directly
-function EmailCell({ getValue }: { getValue: () => string | null }) {
+function EmailCell({ email }: { email: string | null }) {
   const { isHidden } = useHide();
-  const email = getValue();
   if (!email) return <span className="text-gray-400 italic">No email</span>;
   return <span>{isHidden ? maskEmail(email) : email}</span>;
 }

Then in the column definition:

-    cell: ({ getValue }) => (
-      <EmailCell getValue={() => getValue<string | null>()} />
-    ),
+    cell: ({ getValue }) => <EmailCell email={getValue<string | null>()} />,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/PrivyLogins/privyLoginsColumns.tsx` around lines 21 - 23, The cell
wrapper is unnecessarily verbose: instead of passing getValue via a lambda in
the column cell, simplify by either (A) passing getValue directly with a type
assertion (e.g., cell: ({ getValue }) => <EmailCell getValue={getValue as () =>
string | null} />) or (B) refactor EmailCell to accept the resolved value like
AccountEmailCell (change EmailCell's prop from getValue to value: string | null
and update its usages, then use cell: ({ getValue }) => <EmailCell
value={getValue<string | null>()} />); update all references to EmailCell
accordingly so types remain correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/Sandboxes/sandboxesColumns.tsx`:
- Line 26: The title attribute currently exposes the raw email via title={`View
task runs for ${email ?? accountId}`}, so update the logic to respect the
isHidden flag: compute a display value (e.g., use accountId when isHidden is
true, otherwise use email ?? accountId) and use that for the title; reference
the title prop, email, accountId, and isHidden in
sandboxesColumns/SandboxesColumns rendering so the tooltip never reveals the
unmasked email when isHidden is true.

In `@components/SandboxOrgs/AccountReposList.tsx`:
- Line 31: The title attribute on the link in AccountReposList exposes the raw
email (`title={`View task runs for ${email ?? account_id}`}`) even when masking
is enabled; change the display logic to compute a single displayIdentifier
(e.g., use masked value when isHidden is true, otherwise email or account_id)
and use that variable for both the visible label and the title (replace
interpolation in title and any displayLabel usage with displayIdentifier) so the
tooltip no longer reveals the unmasked email.

---

Nitpick comments:
In `@components/PrivyLogins/privyLoginsColumns.tsx`:
- Around line 21-23: The cell wrapper is unnecessarily verbose: instead of
passing getValue via a lambda in the column cell, simplify by either (A) passing
getValue directly with a type assertion (e.g., cell: ({ getValue }) =>
<EmailCell getValue={getValue as () => string | null} />) or (B) refactor
EmailCell to accept the resolved value like AccountEmailCell (change EmailCell's
prop from getValue to value: string | null and update its usages, then use cell:
({ getValue }) => <EmailCell value={getValue<string | null>()} />); update all
references to EmailCell accordingly so types remain correct.

In `@providers/HideProvider.tsx`:
- Around line 27-29: The useHide hook should warn in development when it's used
outside the HideContext provider: retrieve the context with
useContext(HideContext) inside useHide, and if process.env.NODE_ENV !==
'production' and the returned value is undefined (or equals your default
sentinel), call console.warn with a clear message mentioning useHide and
HideContext to help debugging, then return the context value as before; update
the useHide function to perform this check so production behavior is unchanged
but developers get a visible warning when the provider is missing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee8a7a81-7eea-4ed8-8b93-9e0b4b4f8822

📥 Commits

Reviewing files that changed from the base of the PR and between 02228e5 and 8b7ec88.

📒 Files selected for processing (7)
  • components/HideToggle.tsx
  • components/PrivyLogins/privyLoginsColumns.tsx
  • components/SandboxOrgs/AccountReposList.tsx
  • components/Sandboxes/sandboxesColumns.tsx
  • lib/maskEmail.ts
  • providers/HideProvider.tsx
  • providers/Providers.tsx

<Link
href={`/accounts/${accountId}`}
className="text-[#345A5D] hover:underline font-medium"
title={`View task runs for ${email ?? accountId}`}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Title attribute exposes unmasked email when sensitive info is hidden.

Same issue as in AccountReposList.tsx: the tooltip reveals the raw email even when isHidden is true.

🛡️ Proposed fix
-      title={`View task runs for ${email ?? accountId}`}
+      title={`View task runs for ${displayEmail ?? accountId}`}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
title={`View task runs for ${email ?? accountId}`}
title={`View task runs for ${displayEmail ?? accountId}`}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Sandboxes/sandboxesColumns.tsx` at line 26, The title attribute
currently exposes the raw email via title={`View task runs for ${email ??
accountId}`}, so update the logic to respect the isHidden flag: compute a
display value (e.g., use accountId when isHidden is true, otherwise use email ??
accountId) and use that for the title; reference the title prop, email,
accountId, and isHidden in sandboxesColumns/SandboxesColumns rendering so the
tooltip never reveals the unmasked email when isHidden is true.

Prevents the toggle from overlapping the sign-in button
on the login page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- HideToggle is now icon-only (no button background, no label)
- Moved from fixed position in Providers to LoginButton header
  (next to email and sign out)
- Extracted EmailCell to its own component file (SRP)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
import { maskEmail } from "@/lib/maskEmail";
import type { PrivyUser } from "@/types/privy";

function EmailCell({ getValue }: { getValue: () => string | null }) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

SRP - new component file for this definition.

import { maskEmail } from "@/lib/maskEmail";
import type { AccountSandboxRow } from "@/types/sandbox";

function AccountEmailCell({
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

SRP - new component file for this definition.

- AppHeader with LoginButton + HideToggle in root layout (all pages)
- Removed duplicate header from HomePage
- Fixed title tooltips to use masked email when hidden
- Extracted AccountEmailCell from sandboxesColumns (SRP)
- Extracted LastSeenCell from privyLoginsColumns (SRP)
- Moved maskEmail to lib/hide/maskEmail.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/HideToggle.tsx`:
- Around line 10-16: The icon-only toggle button in HideToggle.tsx uses title
only; update the <button> (the element using onClick={toggle}) to include an
accessible name and state by adding a dynamic aria-label based on isHidden
(e.g., "Show sensitive info" when hidden, "Hide sensitive info" when visible)
and an aria-pressed attribute bound to the boolean isHidden (or its inverse
depending on intended semantics); keep the existing title if desired but ensure
aria-label and aria-pressed are present so screen readers announce the control
and its state.

In `@components/Login/LoginButton.tsx`:
- Around line 18-21: The header currently renders the raw email via
user?.email?.address ignoring the hide-mode toggled by HideToggle; update the
LoginButton rendering to read the same hide-state used by HideToggle (e.g., the
hide boolean from the hide context or hook that HideToggle uses) and, when hide
is active, render a masked value (for example "••••••" or a partially masked
address like first char + "...@..." ) instead of the raw email; ensure you
reference the existing symbols user?.email?.address and HideToggle so the check
is co-located with the span that displays the address and use the same
hide-state source (context/hook/prop) as HideToggle to keep behavior consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5f5b9d92-3788-40b2-aa7a-c85c1c89d614

📥 Commits

Reviewing files that changed from the base of the PR and between 14d7afd and f141e99.

📒 Files selected for processing (5)
  • components/HideToggle.tsx
  • components/Login/LoginButton.tsx
  • components/PrivyLogins/EmailCell.tsx
  • components/PrivyLogins/privyLoginsColumns.tsx
  • providers/Providers.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • providers/Providers.tsx
  • components/PrivyLogins/privyLoginsColumns.tsx

<span className="text-sm text-muted-foreground">
{user?.email?.address ?? "Signed in"}
</span>
<HideToggle />
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

SRP - move the hideToggle out of this button into the AppHeader component.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

How can we DRY the email display text changes in both this file and components/PrivyLogins/EmailCell.tsx?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Also components/SandboxOrgs/AccountReposList.tsx

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/PrivyLogins/LastSeenCell.tsx`:
- Around line 7-8: The component LastSeenCell currently uses a falsy check on ts
which treats 0 as "Never"; change the guard to explicitly check for null or
undefined (e.g., ts === null || ts === undefined) so that a timestamp of 0 is
rendered as a date; update the return logic around the ts variable in
LastSeenCell to only show the "Never" span when ts is null/undefined and
otherwise render new Date(ts * 1000).toLocaleString().

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d086738e-2334-4b72-a2c3-ac477e069cd5

📥 Commits

Reviewing files that changed from the base of the PR and between f141e99 and e1bc6d9.

📒 Files selected for processing (10)
  • app/layout.tsx
  • components/AppHeader.tsx
  • components/Home/HomePage.tsx
  • components/PrivyLogins/EmailCell.tsx
  • components/PrivyLogins/LastSeenCell.tsx
  • components/PrivyLogins/privyLoginsColumns.tsx
  • components/SandboxOrgs/AccountReposList.tsx
  • components/Sandboxes/AccountEmailCell.tsx
  • components/Sandboxes/sandboxesColumns.tsx
  • lib/hide/maskEmail.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/PrivyLogins/EmailCell.tsx

- HideToggle: added aria-label, aria-pressed, type=button
- LoginButton: mask header email when hidden
- DRY: created useDisplayEmail hook, used by EmailCell,
  AccountEmailCell, AccountReposList, LoginButton
- LastSeenCell: use == null instead of falsy check for timestamp 0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LoginButton should only handle login/logout. The visibility
toggle is a header-level concern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
repos: AccountRepo[];
}

function AccountRepoLink({ account_id, email }: AccountRepo) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

SRP - new component file for AccountRepoLink

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do not store components in the root of components. Store them in component sub-directories.

  • actual: components/AppHeader.tsx
  • required: components/Header/AppHeader.tsx
    If there's any other components outside of a components/[subDirectory] file please fix those too.

- AppHeader → components/Header/AppHeader.tsx
- HideToggle → components/Header/HideToggle.tsx
- ApiDocsLink → components/ApiDocs/ApiDocsLink.tsx
- Extracted AccountRepoLink from AccountReposList (SRP)
- Updated all imports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
<HomeContent />
</main>
<div className="flex flex-1 items-center justify-center">
<HomeContent />
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

After you moved the header, this content was moved up to the top of the page.

  • required: HomeContent is centered vertically on the page.

title={isHidden ? "Show sensitive info" : "Hide sensitive info"}
className="text-muted-foreground hover:text-foreground transition-colors"
>
{isHidden ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Can you make the transition between these 2 icons appear as though the eye is blinking?
onClick

  1. animate closed
  2. animate open to new icon state

sweetmantech and others added 2 commits March 18, 2026 11:18
On click: eye closes (scaleY 0), icon swaps, eye opens (scaleY 1).
150ms transition for a natural blink effect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Made <main> a flex column container so child flex-1 items-center
can properly fill the remaining height.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Keep scaleY(0) when icon swaps, then animate to scaleY(1) on the
next frame so the opening is a smooth transition instead of a flash.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/layout.tsx`:
- Around line 39-41: RootLayout wraps {children} in a <main> creating nested
main landmarks; remove or replace that wrapper so pages that already render
<main> (e.g., SandboxesPage, PrivyLoginsPage, SandboxOrgsPage) aren’t nested.
Edit the RootLayout (app/layout.tsx) to return children directly or wrap them in
a neutral element (e.g., <div> or fragment) instead of the <main> element so
only route pages supply the primary landmark.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a28c3326-c494-4621-966c-1cc38885e068

📥 Commits

Reviewing files that changed from the base of the PR and between e1bc6d9 and c625d59.

📒 Files selected for processing (15)
  • app/layout.tsx
  • components/ApiDocs/ApiDocsLink.tsx
  • components/Header/AppHeader.tsx
  • components/Header/HideToggle.tsx
  • components/Home/AdminDashboard.tsx
  • components/Login/LoginButton.tsx
  • components/PrivyLogins/EmailCell.tsx
  • components/PrivyLogins/LastSeenCell.tsx
  • components/PrivyLogins/PrivyLoginsPage.tsx
  • components/SandboxOrgs/AccountRepoLink.tsx
  • components/SandboxOrgs/AccountReposList.tsx
  • components/SandboxOrgs/SandboxOrgsPage.tsx
  • components/Sandboxes/AccountEmailCell.tsx
  • components/Sandboxes/SandboxesPage.tsx
  • lib/hide/useDisplayEmail.ts
✅ Files skipped from review due to trivial changes (1)
  • components/Home/AdminDashboard.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • components/Login/LoginButton.tsx
  • components/PrivyLogins/LastSeenCell.tsx
  • components/PrivyLogins/EmailCell.tsx

app/layout.tsx Outdated
Comment on lines +39 to +41
<main className="flex-1">
{children}
</main>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid nested <main> landmarks in RootLayout.

Wrapping children in <main> here causes nested main landmarks because route pages already render <main> (e.g., components/Sandboxes/SandboxesPage.tsx Line 7, components/PrivyLogins/PrivyLoginsPage.tsx Line 20, components/SandboxOrgs/SandboxOrgsPage.tsx Line 7).

Suggested fix
-            <main className="flex-1">
-              {children}
-            </main>
+            <div className="flex-1">
+              {children}
+            </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<main className="flex-1">
{children}
</main>
<div className="flex-1">
{children}
</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/layout.tsx` around lines 39 - 41, RootLayout wraps {children} in a <main>
creating nested main landmarks; remove or replace that wrapper so pages that
already render <main> (e.g., SandboxesPage, PrivyLoginsPage, SandboxOrgsPage)
aren’t nested. Edit the RootLayout (app/layout.tsx) to return children directly
or wrap them in a neutral element (e.g., <div> or fragment) instead of the
<main> element so only route pages supply the primary landmark.

@recoup-coding-agent recoup-coding-agent merged commit 986f25c into main Mar 18, 2026
2 of 3 checks passed
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.

2 participants