Skip to content

feat: platform security foundation, Pro waitlist, and UX improvements - #199

Merged
ayoub3bidi merged 27 commits into
developfrom
feat/add-whishlist
Jul 16, 2026
Merged

feat: platform security foundation, Pro waitlist, and UX improvements#199
ayoub3bidi merged 27 commits into
developfrom
feat/add-whishlist

Conversation

@ayoub3bidi

@ayoub3bidi ayoub3bidi commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Contribution workflow

  • Base branch is develop: This PR targets develop, not main.
  • Guidelines and docs: I have read CONTRIBUTING.md and the docs relevant to my change.
  • This template: I kept the PR template structure and filled in the sections below.

Description

This PR introduces three major pillars of work: a platform security foundation (account banning, access control, edge function infrastructure), a Pro plan waitlist (demand validation before launch), and several UX polish fixes across the app. It touches 79 files with ~4,291 additions and ~408 deletions.

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • 🎨 Style/UI improvement
  • 🧪 Test addition or improvement
  • 📚 Documentation update
  • 🔧 Chore (maintenance, dependencies, etc.)

Changes Made

Platform Security Foundation

  • Account banning system: New before-signup, post-signup, and platform-access Supabase Edge Functions with shared ban logic (banLogic.ts, cors.ts, telegram.ts, webhookVerify.ts)
  • Client-side access control: New accessService.js + authBan.js utilities; AuthProvider now evaluates platform access on every auth state change and tab visibility restore
  • Banned screen: New BannedScreen component shown to banned users with contact info
  • Database migrations: platform_security_foundation.sql (profiles is_banned column + RLS + platform-access RPC), post_signup_webhook_trigger.sql (pg_net webhook for post-signup edge function)
  • SignInPromptModal improvements: Added loading state + error handling for Google sign-in flow
  • Profile settings: Refactored danger zone into modal dialog with confirmation input

Pro Plan Waitlist

  • New /pro page: Full landing page (ProComingSoonPage.jsx) with feature showcase, animated sorting bars, email form, success/already-joined states, and waitlist counter (shown when >50 signups)
  • Waitlist banner: New ProWaitlistBanner component on Landing and App pages with session-scoped dismissal, source attribution (landing/app/direct), RTL support, and smart hiding for already-enrolled users
  • Waitlist service: waitlistService.js with Supabase insert, duplicate detection (23505), email normalization, localStorage caching, public count RPC, and welcome email via edge function
  • Edge function: waitlist-welcome sends confirmation emails via Resend
  • Database migrations: waitlist table with RLS, unique email constraint, source attribution column, waitlist_public_count() RPC

UX Polish and Fixes

  • Dead space fix: Removed excess sm:pt-20 (80px) top padding on /app main content — header is 56px in normal document flow, so the padding created 24px of unnecessary dead space
  • Header simplification on non-/app pages: GitHub repo badge, language switcher, and theme toggle are now hidden on pages other than /app (auto-detected browser language and system theme suffice for first visit; controls available in the visualizer). User avatar hidden when authenticated on non-/app pages; sign-in button remains visible everywhere
  • Insight panel backdrop fix: Backdrop now offsets by 56px on desktop (style={{ top: "56px" }}) to stop blurring the header — matches the existing PythonCodePanel behavior. Added isMobile state with resize listener for responsive backdrop
  • Language switcher: Removed whileHover/whileTap scale animations that caused jarring hover effects
  • Waitlist banner for enrolled users: Banner now checks localStorage for enrolled email and auto-hides, dispatching dismiss event for proper Header sticky behavior
  • Logo navigation: Context-aware — navigates to /app when on landing, / when on app
  • Netlify removal: Cleaned up all Netlify config, CSP checks, and related tests

CI/CD Security

  • OSV-Scanner vulnerability scanning: Replaced broken pnpm audit (npm retired legacy audit endpoints, 410 Gone on pnpm 10.x) with Google OSV-Scanner as a standalone workflow. Two jobs: incremental PR scan (blocks on new vulns) and full scheduled scan (advisory). SARIF upload to Security > Code Scanning tab. Empty osv-scanner.toml for future triage/suppression

Infrastructure and Docs

  • Supabase functions deployment workflow: New deploy-supabase-functions.yml CI workflow
  • Design tokens: Added DESIGN.md, PRODUCT.md, .impeccable/ config for design system documentation
  • AGENTS.md updates: Enhanced with waitlist, security, and auth contract documentation
  • DEVELOPMENT.md: Expanded with Supabase local dev guidance

Related Issues

Closes #

Testing

  • All existing tests pass (pnpm test:run) — 1834 tests passing
  • New tests added for new functionality
  • Manual testing completed

Test Results

Test Files  155 passed (155)
     Tests  1834 passed (1834)

Code Quality

  • Code follows the project coding standards
  • ESLint passes (pnpm lint) — 0 errors
  • Prettier passes (pnpm format:check)
  • No console errors or warnings
  • Code is properly documented with JSDoc

Performance Impact

  • No performance impact

Accessibility

  • Keyboard navigation works correctly
  • Screen reader compatibility maintained
  • Focus indicators are visible

Breaking Changes

  • None

Checklist

  • I have completed the Contribution workflow checklist at the top of this template
  • My code follows the project style guidelines
  • I have performed a self-review of my code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Additional Notes

  • All 3 Supabase migrations are additive-only (no destructive DDL).
  • The before-signup and post-signup edge functions are fail-closed for ban checks; platform-access is fail-open on transport errors to avoid locking out users during outages.
  • OSV-Scanner tracks @main (not pinned to SHA) because v2.3.8 lacks the export-results input needed to prevent 1MB output overflow on large repos. Pin to a specific SHA once a release ships with that input.

ayoub3bidi added 10 commits July 6, 2026 14:32
- Delete netlify.toml (rollback config no longer needed)
- Remove extractCspFromNetlifyToml from scripts/cspHeaders.js
- Remove netlify.toml CSP test from cspHeaders.test.js
- Update AGENTS.md hosting line to drop rollback note
- Update wrangler.jsonc to drop migration-phase comments
… order

- Move DELETE input and delete action into a modal with overlay/Escape/Cancel dismissal
- Reorder modal buttons: Cancel left, Delete account right
- Add cursor-pointer to the Delete account trigger button
- Add common.cancel to all 3 locales (EN/FR/AR)
- Add profile.description and profile.descriptionPlaceholder to all 3 locales
- Import useLocation alongside useNavigate
- Update handleLogoClick to navigate to /app when not on /app, and to / when on /app
- Fix header title descender clipping: leading-none -> leading-tight
- Add Supabase CLI local link cache to .gitignore.
- Expand documentation on Supabase Edge Functions, detailing deployment steps and security measures.
- Refactor main application entry to utilize centralized routing.
- Implement user account access control, including handling for banned accounts and associated UI feedback.
- Update privacy policy to reflect changes in data retention practices.
- Add translations for access ban messages in multiple languages.
- Add entries to .gitignore for Impeccable ephemeral output and runtime state files.
- Update AGENTS.md to reflect increased test coverage and source file counts.
- Document new design agent workflow and Supabase Edge Functions deployment details in AGENTS_REFERENCE.md.
@github-actions github-actions Bot added documentation Improvements or additions to documentation style Improve styling, design, and animation ci Workflows config tests labels Jul 14, 2026
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds platform security and signup controls, a Pro waitlist with email delivery, centralized routing and banned-account handling, shared application-shell updates, deployment automation, Cloudflare CSP validation, and expanded design, product, and operational documentation.

Changes

Platform security and signup enforcement

Layer / File(s) Summary
Security foundation and Edge Functions
src/utils/*, supabase/functions/*, supabase/migrations/*, src/services/accessService.js
Adds IP ban/risk evaluation, webhook verification, signup hooks, platform access checks, account cleanup, security tables, RLS policies, retention jobs, and post-signup triggers.
Auth access state
src/contexts/AuthProvider.jsx, src/services/authService.js, src/services/profileService.js
Tracks banned-account state, refreshes access on auth and visibility changes, handles banned auth errors, exposes profile ban data, and records activity timestamps.

Pro waitlist

Layer / File(s) Summary
Waitlist storage and service flow
supabase/migrations/*waitlist*, src/constants/waitlist.js, src/services/waitlistService.js
Adds waitlist schema, source attribution, public counts, normalized email persistence, duplicate handling, and asynchronous welcome-email invocation.
Waitlist UI and translations
src/pages/ProComingSoonPage.jsx, src/components/ProWaitlistBanner.jsx, src/i18n/locales/*, src/index.css
Adds the /pro signup page, dismissible banner, sorting animation, theme tokens, localized copy, success states, and waitlist-count display.

Application shell and interactions

Layer / File(s) Summary
Central routing and shared navigation
src/AppRoutes.jsx, src/main.jsx, src/components/Header.jsx, src/pages/{LandingPage,Roadmap}.jsx
Moves route registration into AppRoutes, adds /pro and banned-account rendering, and consolidates shared header behavior across pages.
Sign-in and account settings feedback
src/components/{SignInPromptModal,UserMenu}.jsx, src/pages/ProfileSettingsPage.jsx, src/components/ui/Button.jsx
Adds sign-in loading/error states, cursor states, and an animated delete-account confirmation modal.
Metadata and supporting UI updates
src/components/DocumentTitle.jsx, src/components/Footer.jsx, src/components/LanguageSwitcher.jsx, src/components/landing/RoadmapCTA.jsx
Updates Pro metadata, social-link styling, language-switcher motion, footer hover behavior, and Roadmap CTA structure.

Deployment and project contracts

Layer / File(s) Summary
Deployment and CSP migration
.github/workflows/deploy-supabase-functions.yml, scripts/cspHeaders.js, src/security/cspHeaders.test.js, wrangler.jsonc
Adds CI-triggered Supabase function deployment and switches CSP extraction/tests from Netlify configuration to Cloudflare headers.
Design, product, and operational documentation
DESIGN.md, PRODUCT.md, AGENTS.md, docs/*
Documents design tokens, product positioning, routes, security contracts, Edge Functions, waitlist schema, deployment procedures, and administrative runbooks.
Repository tooling and generated configuration
.gitignore, .impeccable/*, eslint.config.js, public/sitemap.xml
Adds local-tool ignores and configuration, ignores .cursor, and publishes the /pro sitemap entry.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant Visitor
  participant ProComingSoonPage
  participant waitlistService
  participant Supabase
  participant waitlistWelcome
  participant Resend
  Visitor->>ProComingSoonPage: Submit email
  ProComingSoonPage->>waitlistService: joinWaitlist(email, source)
  waitlistService->>Supabase: Insert waitlist row
  waitlistService->>Supabase: Read public waitlist count
  waitlistService->>waitlistWelcome: Invoke welcome function
  waitlistWelcome->>Resend: Send confirmation email
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main themes of the PR: platform security, the Pro waitlist, and UX improvements.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add-whishlist

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.

@ayoub3bidi ayoub3bidi self-assigned this Jul 14, 2026
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

Preview for Bayan Flow Staging ready!

Name Link
🔨 Latest commit f6219c0
🔍 Latest deploy log https://github.com/ayoub3bidi/bayan-flow/actions/runs/29484229885
😎 Deploy Preview https://pr-199-bayan-flow-staging.ayoub3bidi.workers.dev
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

Preview alias pr-199 on the staging worker. Updates automatically with new commits.

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.83041% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/pages/ProComingSoonPage.jsx 97.45% 6 Missing ⚠️
src/components/UserMenu.jsx 92.85% 3 Missing ⚠️
src/components/BannedScreen.jsx 96.55% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

- Remove inert Tailwind utilities activated by @config (hover:bg-surface-elevated in Footer)
- Remove fixed gradient overlay (from-bg via-bg to-surface-elevated) from LandingPage, LegalDocument, and ProComingSoonPage — this was transparent on main but renders a lighter-to-dark gradient in dark mode, causing a 'backlight' effect
- Remove RoadmapCTA decorative elements (gradient overlay, glow orb, badge pill) that rendered unintentionally due to @config activating previously dead utilities
- Make Header non-sticky (always relative, never sm:fixed)
- Show 'Sign in with Google' text on non-/app pages; icon-only on /app
- Update tests to match removed elements

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 17

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pages/VisualizerApp.jsx (1)

639-646: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Ensure the "Skip to main content" link remains the first focusable element.

Placing the ProWaitlistBanner before the "Skip to main content" link introduces focusable elements (the banner's CTA link and dismiss button) before the skip link. This forces keyboard-only and screen-reader users to navigate through the banner before they can skip to the main content, degrading accessibility.

Move the ProWaitlistBanner below the skip navigation link.

♿ Proposed fix
-      <ProWaitlistBanner source="app" />
       {/* Skip Navigation Link */}
       <a
         href="`#main-content`"
         className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-blue-600 focus:text-white focus:rounded-md focus:shadow-lg"
       >
         Skip to main content
       </a>
+      <ProWaitlistBanner source="app" />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/VisualizerApp.jsx` around lines 639 - 646, Move the
ProWaitlistBanner component below the “Skip to main content” anchor in
VisualizerApp, ensuring the skip-navigation link remains the first focusable
element while preserving the banner’s existing rendering.
🟡 Minor comments (4)
supabase/functions/before-signup/index.ts-66-66 (1)

66-66: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Avoid logging the raw email address.

console.warn here logs the user's email in plaintext. Consider omitting it or logging a redacted/hashed identifier instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/before-signup/index.ts` at line 66, Update the warning in
the before-signup handler for missing metadata.ip_address to stop logging the
raw email address. Omit the email from the console.warn context or replace it
with a redacted or hashed identifier while preserving the warning message.
supabase/functions/waitlist-welcome/index.ts-39-66 (1)

39-66: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

position parameter is unused in the email template.

buildEmailHtml accepts position but the returned subject/html never reference it, so the queue-position feature implied by the parameter (and by the surrounding migration comment about "position display") never reaches the email content. Either wire it into the copy or drop the dead parameter.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/waitlist-welcome/index.ts` around lines 39 - 66, The
buildEmailHtml function accepts an unused position parameter; either incorporate
position into the returned subject or html to display the recipient’s queue
position, or remove the parameter and update its callers if position is not
intended to appear. Ensure the chosen behavior matches the surrounding waitlist
position-display requirement.
src/contexts/AuthProvider.jsx-110-120 (1)

110-120: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Log non-ban getUser() failures before falling through. AccountBannedError is the only special case here; any other error from authService.getUser() is currently swallowed and the flow continues to checkPlatformAccess(), which can hide auth/network issues. src/contexts/AuthProvider.jsx:110-120

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/contexts/AuthProvider.jsx` around lines 110 - 120, Update the getUser()
catch block in AuthProvider to log non-AccountBannedError failures before
continuing to checkPlatformAccess(). Preserve the existing stale-check guard and
account_banned handling, and ensure only the non-ban error path is logged.
src/i18n/locales/fr/translation.json-64-111 (1)

64-111: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix French grammatical errors in waitlist copy.

A couple of phrases use incorrect grammar ("le Plan Pro" instead of "du Plan Pro") and contain an errant space before a period.

✏️ Proposed fixes

Apply these updates to correct the French phrasing:

-    "metaDescription": "Rejoignez la liste d'attente le Plan Pro et sécurisez 50 % de réduction sur votre première année au plan annuel.",
+    "metaDescription": "Rejoignez la liste d'attente du Plan Pro et sécurisez 50 % de réduction sur votre première année au plan annuel.",

And update the alreadyJoined body text:

     "alreadyJoined": {
       "title": "Vous êtes déjà inscrit",
-      "body": "Nous avons déjà votre e-mail. Nous vous préviendrons au lancement de le plan pro ."
+      "body": "Nous avons déjà votre e-mail. Nous vous préviendrons au lancement du Plan Pro."
     },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/i18n/locales/fr/translation.json` around lines 64 - 111, Correct the
French waitlist copy in the locale entries, changing the affected “le Plan Pro”
phrasing to the grammatically correct “du Plan Pro” and removing the extra space
before the period in the alreadyJoined.body text. Preserve all other
translations and keys unchanged.
🧹 Nitpick comments (8)
supabase/functions/delete-account/index.ts (1)

89-93: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Comment overstates the effect of the explicit false argument.

Per Supabase's docs, shouldSoftDelete defaults to false (permanent delete), so the previous call (without a second argument) was already a hard delete — this change doesn't alter reuse behavior, just makes the existing default explicit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/delete-account/index.ts` around lines 89 - 93, Update the
comment above the supabaseAdmin.auth.admin.deleteUser call to accurately state
that the explicit false argument preserves the default permanent-delete
behavior, without claiming it newly enables immediate Google email reuse.
supabase/functions/_shared/cors.ts (1)

37-43: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Consider adding Vary: Origin when echoing the request Origin.

Since Access-Control-Allow-Origin is computed per-request based on the incoming Origin header, add Vary: Origin to avoid a caching layer (if any is ever introduced in front of these functions) serving one origin's CORS headers to another origin's request.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_shared/cors.ts` around lines 37 - 43, Add a "Vary:
Origin" response header in buildCorsHeaders alongside the computed
Access-Control-Allow-Origin header, preserving the existing origin resolution
and other CORS headers.
supabase/migrations/20260710150000_pro_waitlist_attribution.sql (1)

1-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Migration appears entirely redundant with 20260710140000_pro_waitlist.sql.

supabase/migrations/20260710140000_pro_waitlist.sql (which runs first by timestamp) already creates public.waitlist with the identical source column/check, the identical waitlist_source_idx index, and an identical waitlist_public_count() function with the same grants. Every statement here is a guarded no-op (IF NOT EXISTS / CREATE OR REPLACE) against that schema, so this file adds no schema change in practice — worth double-checking this wasn't left behind after the base migration was later edited to embed what this file originally added.

Since the index already exists when this statement runs, the Squawk require-concurrent-index-creation hint on line 10 doesn't apply in practice here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/migrations/20260710150000_pro_waitlist_attribution.sql` around lines
1 - 24, Remove the redundant migration contents from the migration that
duplicates the waitlist schema, index, RPC, and grants already established by
the earlier waitlist migration. Ensure the migration no longer reissues the
guarded ALTER, index creation, function replacement, or privilege statements,
preserving the earlier migration as the single source of truth.

Source: Linters/SAST tools

src/pages/Roadmap.jsx (1)

8-15: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove unused useTranslation import and hook call.

The t function is no longer used in this component since the language switcher and "back" controls were moved into the Header component. Removing it resolves the linter warning.

♻️ Proposed refactor
 import { useEffect } from 'react';
-import { useTranslation } from 'react-i18next';
 import RoadmapHero from '../components/roadmap/RoadmapHero';
 import Timeline from '../components/roadmap/Timeline';
 import Footer from '../components/Footer';
 import Header from '../components/Header';
 
 function Roadmap() {
-  const { t } = useTranslation();
-
   // Scroll to top when component mounts
   useEffect(() => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/Roadmap.jsx` around lines 8 - 15, Remove the unused useTranslation
import and the corresponding t hook call from the Roadmap component, leaving the
remaining imports and component behavior unchanged.

Source: Linters/SAST tools

src/pages/ProComingSoonPage.jsx (2)

271-278: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Error-message branch untested.

codecov flags lines 272-278 (the invalid_email/unavailable/generic error rendering) as uncovered; ProComingSoonPage.test.jsx only exercises success and already-joined paths.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/ProComingSoonPage.jsx` around lines 271 - 278, Extend
ProComingSoonPage.test.jsx with coverage for the errorKey rendering branch in
ProComingSoonPage, exercising invalid_email, unavailable, and generic error
cases as appropriate. Assert that the alert with id pro-waitlist-email-error
renders the translated error message, while preserving the existing success and
already-joined tests.

Source: Linters/SAST tools


71-71: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Dead position state and commented-out JSX.

position/setPosition are set but never rendered (only consumer is the commented-out TODO block), matching the CI "unused var" warnings on line 71. Since it's parked for later reinstatement, consider dropping the state now and re-adding it (with the JSX) when the feature returns — git history preserves the commented block.

Also applies to: 102-102, 204-209

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/ProComingSoonPage.jsx` at line 71, Remove the unused position state
declaration and its setter from ProComingSoonPage, along with the associated
commented-out JSX/TODO block that is its only consumer. Leave the active page
behavior unchanged and reintroduce this state only when the related feature is
implemented.

Source: Linters/SAST tools

src/utils/authBan.test.js (1)

17-28: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add coverage for the untested isSignInBlockedError branches.

'signup is disabled' and 'User not allowed' message branches aren't exercised.

✅ Suggested additional assertions
     expect(
       isSignInBlockedError({ message: 'Invalid payload sent to hook' })
     ).toBe(true);
+    expect(
+      isSignInBlockedError({ message: 'User not allowed to sign in' })
+    ).toBe(true);
+    expect(
+      isSignInBlockedError({ message: 'signup is disabled for this project' })
+    ).toBe(true);
     expect(isSignInBlockedError({ code: 'unexpected_failure' })).toBe(true);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/authBan.test.js` around lines 17 - 28, Add assertions to the
existing “detects blocked sign-in errors” test for isSignInBlockedError,
covering messages “signup is disabled” and “User not allowed” and expecting both
to return true. Preserve the current cases and expectations.
src/contexts/AuthProvider.jsx (1)

61-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Ref mutated during render (flagged by static analysis).

userRef.current = user executes unconditionally in the component body, which React's rendering-purity rules discourage since render can be replayed/discarded without committing. Functionally safe here today (only consumed from the visibilitychange listener, not read during render), but consider moving the assignment into a useEffect/useLayoutEffect for correctness under React 19 concurrent semantics.

♻️ Optional refactor
-  const userRef = useRef(null);
-  userRef.current = user;
+  const userRef = useRef(null);
+  useEffect(() => {
+    userRef.current = user;
+  }, [user]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/contexts/AuthProvider.jsx` around lines 61 - 65, Move the userRef.current
assignment out of the AuthProvider render body and into an effect that runs when
user changes, while preserving the existing userRef usage by the
visibilitychange listener.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/deploy-supabase-functions.yml:
- Around line 17-20: Add a head_repository check to the workflow_run condition
in the deployment workflow, requiring
github.event.workflow_run.head_repository.full_name to equal github.repository
alongside the existing successful main/develop branch checks. Preserve
deployment behavior for successful base-repository runs while preventing
fork-originated workflows from executing.

In `@src/components/ProWaitlistBanner.jsx`:
- Around line 71-77: Update ProWaitlistBannerContent to accept the inRouter
boolean from ProWaitlistBanner and conditionally render the CTA as a React
Router Link when true, or a regular anchor using the same destination and
relevant attributes when false. Ensure both the primary CTA and the additionally
referenced banner link avoid Link rendering outside a Router context.

In `@src/contexts/AuthProvider.jsx`:
- Around line 90-108: Update the !activeUser branch of evaluateAccess to clear
the stored profile row by invoking refreshProfile(null) before returning, while
preserving the existing access-block reset and stale-check behavior. Ensure
hydrate and onAuthStateChange sign-out/session-loss paths remove the previous
user’s profile data.

In `@src/index.css`:
- Around line 578-755: Rename all proSort0–proSort5 keyframes to kebab-case
pro-sort-0 through pro-sort-5 and update the matching animation references in
the pro-sorting-tile-1 through pro-sorting-tile-6 rules. Add narrowly scoped
stylelint suppression around these intentional duplicate keyframe selectors so
the existing hold-and-jump animation timing remains unchanged.

In `@src/pages/ProComingSoonPage.jsx`:
- Around line 59-77: Prevent the default-email synchronization in the
ProComingSoonPage component from overwriting user input: track whether the email
field has been edited, mark it edited in the input/change handler, and make the
defaultEmail effect update email only while the field remains unedited. Preserve
applying asynchronously resolved profile, user, or stored email values before
any user edit.

In `@src/pages/ProfileSettingsPage.jsx`:
- Around line 469-492: Update the delete modal flow in ProfileSettingsPage
around the motion.div dialog so opening it moves initial focus into the dialog,
allowing Escape to trigger its existing onKeyDown dismissal immediately while
preserving the current close and confirmation-text reset behavior.

In `@src/security/cspHeaders.test.js`:
- Line 10: Restore expect to the vitest import in cspHeaders.test.js, alongside
describe, it, vi, and beforeEach, so the existing assertions resolve correctly.

In `@src/services/accessService.js`:
- Around line 22-47: Update checkPlatformAccess so the supabase.functions.invoke
call is bounded by a request timeout or timeout race. When the timeout expires,
handle it through the existing catch/fail-open path, returning allowed: true
with failOpen: true so evaluateAccess and AuthProvider hydration cannot remain
pending.

In `@src/services/waitlistService.js`:
- Around line 46-52: Update persistWaitlistEmail and readStoredWaitlistEmail to
use sessionStorage instead of localStorage, keeping the existing
WAITLIST_EMAIL_STORAGE_KEY and error-handling behavior. Ensure reads and writes
are session-scoped so the cleartext email is not retained across browser
sessions.

In `@supabase/functions/_shared/telegram.ts`:
- Around line 8-33: Add an AbortController-based timeout to the fetch call in
sendTelegramAlert, passing its signal and aborting after a bounded duration so
an unresponsive Telegram API cannot block the awaited request indefinitely.
Preserve the existing request payload and non-OK response logging.

In `@supabase/functions/before-signup/index.ts`:
- Around line 65-74: Update the invalid-IP branch in the before-signup handler
so missing or invalid metadata.ip_address does not immediately allow signup or
bypass trusted_ips, banned_ips, and rate-limit enforcement. Make this path fail
closed using the function’s established rejection or conservative-default
behavior, while preserving signup_pending recording as appropriate and ensuring
valid IPs continue through the existing checks.

In `@supabase/functions/delete-account/index.ts`:
- Around line 57-93: Refactor the delete-account flow around the cleanup queries
and auth.admin.deleteUser so profile, signup_events, signup_pending cleanup, and
account deletion execute atomically through a single transactional Postgres RPC
or equivalent database function. Ensure any failure rolls back all cleanup
changes and only report success after every operation completes.

In `@supabase/functions/post-signup/index.ts`:
- Around line 69-117: Handle and surface Supabase errors for every query in the
post-signup flow, including the pending lookup, profile update, signup event
insert, banned-IP lookup, IP-event lookup, and pending cleanup. Update each call
to inspect its returned error and log or propagate it using the function’s
established error-handling mechanism, while preserving the existing no-row
behavior for successful queries.

In `@supabase/functions/waitlist-welcome/index.ts`:
- Line 104: Update handleRequest to prevent repeated welcome-email sends by
atomically checking and recording a sent state on the waitlist record (using an
appropriate welcomed_at or equivalent column), while preserving safe behavior
for already-processed entries. Add basic rate limiting for unauthenticated
requests, and make waitlist lookup responses indistinguishable for existing
versus non-existing emails so membership cannot be enumerated.

In `@supabase/migrations/20260710120000_platform_security_foundation.sql`:
- Around line 102-118: Remove last_active_at from the authenticated role’s
direct column UPDATE grant, leaving only display_name and avatar_preference
writable. Keep touch_last_active() and its authenticated EXECUTE grant so
last_active_at can be changed exclusively through the RPC.

In `@supabase/migrations/20260710130000_post_signup_webhook_trigger.sql`:
- Around line 17-46: Replace the hardcoded Supabase project URL in the
net.http_post call with an environment-aware configuration value, reusing the
project’s established configuration mechanism. Ensure each environment resolves
its own post-signup function endpoint while preserving the existing webhook
payload, headers, and secret handling.

In `@supabase/migrations/20260710160000_drop_waitlist_pitch_variant.sql`:
- Line 3: Remove the destructive waitlist schema change by deleting the ALTER
TABLE statement that drops pitch_variant. Keep the column in place for backward
compatibility, and defer its removal until all deployed application and Edge
Function clients no longer reference it.

---

Outside diff comments:
In `@src/pages/VisualizerApp.jsx`:
- Around line 639-646: Move the ProWaitlistBanner component below the “Skip to
main content” anchor in VisualizerApp, ensuring the skip-navigation link remains
the first focusable element while preserving the banner’s existing rendering.

---

Minor comments:
In `@src/contexts/AuthProvider.jsx`:
- Around line 110-120: Update the getUser() catch block in AuthProvider to log
non-AccountBannedError failures before continuing to checkPlatformAccess().
Preserve the existing stale-check guard and account_banned handling, and ensure
only the non-ban error path is logged.

In `@src/i18n/locales/fr/translation.json`:
- Around line 64-111: Correct the French waitlist copy in the locale entries,
changing the affected “le Plan Pro” phrasing to the grammatically correct “du
Plan Pro” and removing the extra space before the period in the
alreadyJoined.body text. Preserve all other translations and keys unchanged.

In `@supabase/functions/before-signup/index.ts`:
- Line 66: Update the warning in the before-signup handler for missing
metadata.ip_address to stop logging the raw email address. Omit the email from
the console.warn context or replace it with a redacted or hashed identifier
while preserving the warning message.

In `@supabase/functions/waitlist-welcome/index.ts`:
- Around line 39-66: The buildEmailHtml function accepts an unused position
parameter; either incorporate position into the returned subject or html to
display the recipient’s queue position, or remove the parameter and update its
callers if position is not intended to appear. Ensure the chosen behavior
matches the surrounding waitlist position-display requirement.

---

Nitpick comments:
In `@src/contexts/AuthProvider.jsx`:
- Around line 61-65: Move the userRef.current assignment out of the AuthProvider
render body and into an effect that runs when user changes, while preserving the
existing userRef usage by the visibilitychange listener.

In `@src/pages/ProComingSoonPage.jsx`:
- Around line 271-278: Extend ProComingSoonPage.test.jsx with coverage for the
errorKey rendering branch in ProComingSoonPage, exercising invalid_email,
unavailable, and generic error cases as appropriate. Assert that the alert with
id pro-waitlist-email-error renders the translated error message, while
preserving the existing success and already-joined tests.
- Line 71: Remove the unused position state declaration and its setter from
ProComingSoonPage, along with the associated commented-out JSX/TODO block that
is its only consumer. Leave the active page behavior unchanged and reintroduce
this state only when the related feature is implemented.

In `@src/pages/Roadmap.jsx`:
- Around line 8-15: Remove the unused useTranslation import and the
corresponding t hook call from the Roadmap component, leaving the remaining
imports and component behavior unchanged.

In `@src/utils/authBan.test.js`:
- Around line 17-28: Add assertions to the existing “detects blocked sign-in
errors” test for isSignInBlockedError, covering messages “signup is disabled”
and “User not allowed” and expecting both to return true. Preserve the current
cases and expectations.

In `@supabase/functions/_shared/cors.ts`:
- Around line 37-43: Add a "Vary: Origin" response header in buildCorsHeaders
alongside the computed Access-Control-Allow-Origin header, preserving the
existing origin resolution and other CORS headers.

In `@supabase/functions/delete-account/index.ts`:
- Around line 89-93: Update the comment above the
supabaseAdmin.auth.admin.deleteUser call to accurately state that the explicit
false argument preserves the default permanent-delete behavior, without claiming
it newly enables immediate Google email reuse.

In `@supabase/migrations/20260710150000_pro_waitlist_attribution.sql`:
- Around line 1-24: Remove the redundant migration contents from the migration
that duplicates the waitlist schema, index, RPC, and grants already established
by the earlier waitlist migration. Ensure the migration no longer reissues the
guarded ALTER, index creation, function replacement, or privilege statements,
preserving the earlier migration as the single source of truth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c8e773d9-a46a-4232-9260-b23b167b1e03

📥 Commits

Reviewing files that changed from the base of the PR and between 5862be1 and a2b5f04.

📒 Files selected for processing (83)
  • .github/workflows/deploy-supabase-functions.yml
  • .gitignore
  • .impeccable/config.json
  • .impeccable/design.json
  • .impeccable/live/config.json
  • AGENTS.md
  • DESIGN.md
  • PRODUCT.md
  • docs/AGENTS_REFERENCE.md
  • docs/DEVELOPMENT.md
  • eslint.config.js
  • netlify.toml
  • public/sitemap.xml
  • scripts/cspHeaders.js
  • src/AppRoutes.jsx
  • src/AppRoutes.test.jsx
  • src/components/BannedScreen.jsx
  • src/components/BannedScreen.test.jsx
  • src/components/DocumentTitle.jsx
  • src/components/DocumentTitle.test.jsx
  • src/components/Footer.jsx
  • src/components/Header.jsx
  • src/components/LanguageSwitcher.jsx
  • src/components/LegalDocument.jsx
  • src/components/LegalDocument.test.jsx
  • src/components/ProWaitlistBanner.jsx
  • src/components/ProWaitlistBanner.test.jsx
  • src/components/SignInPromptModal.jsx
  • src/components/SignInPromptModal.test.jsx
  • src/components/UserMenu.jsx
  • src/components/UserMenu.test.jsx
  • src/components/landing/RoadmapCTA.jsx
  • src/components/landing/RoadmapCTA.test.jsx
  • src/components/ui/Button.jsx
  • src/constants/waitlist.js
  • src/content/legal/privacy.en.js
  • src/contexts/AuthContextDefinition.js
  • src/contexts/AuthProvider.jsx
  • src/contexts/AuthProvider.test.jsx
  • src/i18n/locales/ar/translation.json
  • src/i18n/locales/en/translation.json
  • src/i18n/locales/fr/translation.json
  • src/index.css
  • src/main.jsx
  • src/pages/LandingPage.jsx
  • src/pages/LandingPage.test.jsx
  • src/pages/PrivacyPolicy.test.jsx
  • src/pages/ProComingSoonPage.jsx
  • src/pages/ProComingSoonPage.test.jsx
  • src/pages/ProfileSettingsPage.jsx
  • src/pages/ProfileSettingsPage.test.jsx
  • src/pages/Roadmap.jsx
  • src/pages/Roadmap.test.jsx
  • src/pages/TermsOfUse.test.jsx
  • src/pages/VisualizerApp.jsx
  • src/pages/VisualizerApp.test.jsx
  • src/security/cspHeaders.test.js
  • src/services/accessService.js
  • src/services/accessService.test.js
  • src/services/authService.js
  • src/services/profileService.js
  • src/services/waitlistService.js
  • src/services/waitlistService.test.js
  • src/test/supabaseMock.js
  • src/utils/authBan.js
  • src/utils/authBan.test.js
  • src/utils/banLogic.js
  • src/utils/banLogic.test.js
  • supabase/functions/_shared/banLogic.ts
  • supabase/functions/_shared/cors.ts
  • supabase/functions/_shared/telegram.ts
  • supabase/functions/_shared/webhookVerify.ts
  • supabase/functions/before-signup/index.ts
  • supabase/functions/delete-account/index.ts
  • supabase/functions/platform-access/index.ts
  • supabase/functions/post-signup/index.ts
  • supabase/functions/waitlist-welcome/index.ts
  • supabase/migrations/20260710120000_platform_security_foundation.sql
  • supabase/migrations/20260710130000_post_signup_webhook_trigger.sql
  • supabase/migrations/20260710140000_pro_waitlist.sql
  • supabase/migrations/20260710150000_pro_waitlist_attribution.sql
  • supabase/migrations/20260710160000_drop_waitlist_pitch_variant.sql
  • wrangler.jsonc
💤 Files with no reviewable changes (4)
  • src/components/LanguageSwitcher.jsx
  • wrangler.jsonc
  • netlify.toml
  • scripts/cspHeaders.js

Comment thread .github/workflows/deploy-supabase-functions.yml
Comment thread src/components/ProWaitlistBanner.jsx Outdated
Comment thread src/contexts/AuthProvider.jsx
Comment thread src/index.css Outdated
Comment thread src/pages/ProComingSoonPage.jsx
Comment thread supabase/functions/post-signup/index.ts Outdated
Comment thread supabase/functions/waitlist-welcome/index.ts
Comment thread supabase/migrations/20260710120000_platform_security_foundation.sql
Comment on lines +17 to +46
begin
select ds.decrypted_secret into webhook_secret
from vault.decrypted_secrets ds
where ds.name = 'post_signup_webhook_secret'
limit 1;

if webhook_secret is null then
raise warning 'post_signup_webhook_secret missing from vault';
return NEW;
end if;

payload := jsonb_build_object(
'type', TG_OP,
'table', TG_TABLE_NAME,
'schema', TG_TABLE_SCHEMA,
'record', to_jsonb(NEW),
'old_record', null
);

headers := jsonb_build_object(
'Content-Type', 'application/json',
'x-webhook-secret', webhook_secret
);

perform net.http_post(
url := 'https://qketsapzqpzmccljfjcm.supabase.co/functions/v1/post-signup',
headers := headers,
body := payload
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Hardcoded project URL breaks portability across environments.

The webhook secret is externalized via vault, but the target URL at Line 42 is hardcoded to one specific project ref. Replaying this migration in another environment (staging/preview) will send webhook calls to the wrong (or production) project.

🔧 Suggested approach
+  select ds.decrypted_secret into webhook_url
+  from vault.decrypted_secrets ds
+  where ds.name = 'post_signup_webhook_url'
+  limit 1;
+
   perform net.http_post(
-    url := 'https://qketsapzqpzmccljfjcm.supabase.co/functions/v1/post-signup',
+    url := coalesce(webhook_url, 'https://qketsapzqpzmccljfjcm.supabase.co/functions/v1/post-signup'),
     headers := headers,
     body := payload
   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/migrations/20260710130000_post_signup_webhook_trigger.sql` around
lines 17 - 46, Replace the hardcoded Supabase project URL in the net.http_post
call with an environment-aware configuration value, reusing the project’s
established configuration mechanism. Ensure each environment resolves its own
post-signup function endpoint while preserving the existing webhook payload,
headers, and secret handling.

Comment thread supabase/migrations/20260710160000_drop_waitlist_pitch_variant.sql Outdated
Security:
- Restrict deploy-supabase-functions workflow to base repository only (#1)
- Fail-closed on missing IP metadata in before-signup hook (#11)
- Switch waitlist email from localStorage to sessionStorage (#9)
- Remove last_active_at from direct client UPDATE grant; use security definer RPC (#15)

Functional correctness:
- Clear profileRow on implicit sign-out in AuthProvider (#3)
- Prevent email useEffect from clobbering user input on ProComingSoonPage (#5)
- Add autoFocus to delete modal for immediate Escape dismissal (#6)
- Fix Link rendering outside Router context in ProWaitlistBanner (#2)
- Move skip-to-content link above ProWaitlistBanner for a11y (#18)

Stability & hardening:
- Add timeout to supabase.functions.invoke in accessService (#8)
- Add AbortSignal.timeout to Telegram fetch call (#10)
- Reorder delete-account to deleteUser before cleanup for atomicity (#12)
- Add error handling for all Supabase calls in post-signup (#13)
- Add idempotency guard (welcomed_at) to waitlist-welcome (#14)

Code quality:
- Rename proSort0-5 to kebab-case pro-sort-0-5 with stylelint suppression (#4)
- Restore expect import in cspHeaders.test (#7)
- Revert destructive column drop in migration (#17)
- Add new migration for welcomed_at column (#14)

Tests:
- Add test for implicit sign-out profile clearing (AuthProvider)
- Add test for email input not clobbered by async auth (ProComingSoonPage)
- Add test for Escape dismissing delete modal (ProfileSettingsPage)
- Add test for anchor rendering outside Router (ProWaitlistBanner)
npm retired the /-/npm/v1/security/audits endpoint, causing
pnpm audit to fail with 410 on every CI run. Use the built-in
--ignore-registry-errors flag so the audit still runs when the
registry is available but doesn't block CI when it's down.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/pages/ProComingSoonPage.jsx (1)

72-72: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove unused position state.

The position state variable is declared here and updated on line 105, but its usage in the JSX (lines 207-212) is currently commented out. This triggers a lint warning for an unused variable. Consider removing the state and its corresponding setPosition call until the UI is ready to be re-enabled.

♻️ Proposed refactor

Remove the state declaration:

-  const [position, setPosition] = useState(null);

And also remove the state update further down in the file (around line 105):

    if (result.status === 'joined') {
-     setPosition(result.position ?? null);
      setSubmitState('success');
      return;
    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/ProComingSoonPage.jsx` at line 72, Remove the unused position state
declaration in the component and delete the corresponding setPosition call in
the joined-result branch of the submission handler, while leaving the existing
submitState behavior unchanged.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/security/cspHeaders.test.js`:
- Line 10: Remove the unused expect import from the Vitest import declaration in
the cspHeaders test file, while preserving the remaining describe, it, vi, and
beforeEach imports.

---

Nitpick comments:
In `@src/pages/ProComingSoonPage.jsx`:
- Line 72: Remove the unused position state declaration in the component and
delete the corresponding setPosition call in the joined-result branch of the
submission handler, while leaving the existing submitState behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 637c2c24-3141-4b16-8c1b-f06f066ac3ae

📥 Commits

Reviewing files that changed from the base of the PR and between a2b5f04 and 805eabb.

📒 Files selected for processing (24)
  • .github/workflows/deploy-supabase-functions.yml
  • src/components/Footer.jsx
  • src/components/ProWaitlistBanner.jsx
  • src/components/ProWaitlistBanner.test.jsx
  • src/contexts/AuthProvider.jsx
  • src/contexts/AuthProvider.test.jsx
  • src/index.css
  • src/pages/ProComingSoonPage.jsx
  • src/pages/ProComingSoonPage.test.jsx
  • src/pages/ProfileSettingsPage.jsx
  • src/pages/ProfileSettingsPage.test.jsx
  • src/pages/VisualizerApp.jsx
  • src/security/cspHeaders.test.js
  • src/services/accessService.js
  • src/services/waitlistService.js
  • src/services/waitlistService.test.js
  • supabase/functions/_shared/telegram.ts
  • supabase/functions/before-signup/index.ts
  • supabase/functions/delete-account/index.ts
  • supabase/functions/post-signup/index.ts
  • supabase/functions/waitlist-welcome/index.ts
  • supabase/migrations/20260710120000_platform_security_foundation.sql
  • supabase/migrations/20260710160000_drop_waitlist_pitch_variant.sql
  • supabase/migrations/20260715200000_add_welcomed_at_to_waitlist.sql
🚧 Files skipped from review as they are similar to previous changes (16)
  • supabase/functions/_shared/telegram.ts
  • src/services/accessService.js
  • src/pages/VisualizerApp.jsx
  • src/components/ProWaitlistBanner.jsx
  • src/pages/ProfileSettingsPage.test.jsx
  • .github/workflows/deploy-supabase-functions.yml
  • supabase/functions/post-signup/index.ts
  • src/pages/ProComingSoonPage.test.jsx
  • src/components/Footer.jsx
  • src/services/waitlistService.js
  • src/index.css
  • src/pages/ProfileSettingsPage.jsx
  • src/services/waitlistService.test.js
  • supabase/functions/delete-account/index.ts
  • supabase/migrations/20260710120000_platform_security_foundation.sql
  • src/contexts/AuthProvider.jsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/pages/ProComingSoonPage.jsx (1)

72-72: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove unused position state.

The position state variable is declared here and updated on line 105, but its usage in the JSX (lines 207-212) is currently commented out. This triggers a lint warning for an unused variable. Consider removing the state and its corresponding setPosition call until the UI is ready to be re-enabled.

♻️ Proposed refactor

Remove the state declaration:

-  const [position, setPosition] = useState(null);

And also remove the state update further down in the file (around line 105):

    if (result.status === 'joined') {
-     setPosition(result.position ?? null);
      setSubmitState('success');
      return;
    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/ProComingSoonPage.jsx` at line 72, Remove the unused position state
declaration in the component and delete the corresponding setPosition call in
the joined-result branch of the submission handler, while leaving the existing
submitState behavior unchanged.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/security/cspHeaders.test.js`:
- Line 10: Remove the unused expect import from the Vitest import declaration in
the cspHeaders test file, while preserving the remaining describe, it, vi, and
beforeEach imports.

---

Nitpick comments:
In `@src/pages/ProComingSoonPage.jsx`:
- Line 72: Remove the unused position state declaration in the component and
delete the corresponding setPosition call in the joined-result branch of the
submission handler, while leaving the existing submitState behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 637c2c24-3141-4b16-8c1b-f06f066ac3ae

📥 Commits

Reviewing files that changed from the base of the PR and between a2b5f04 and 805eabb.

📒 Files selected for processing (24)
  • .github/workflows/deploy-supabase-functions.yml
  • src/components/Footer.jsx
  • src/components/ProWaitlistBanner.jsx
  • src/components/ProWaitlistBanner.test.jsx
  • src/contexts/AuthProvider.jsx
  • src/contexts/AuthProvider.test.jsx
  • src/index.css
  • src/pages/ProComingSoonPage.jsx
  • src/pages/ProComingSoonPage.test.jsx
  • src/pages/ProfileSettingsPage.jsx
  • src/pages/ProfileSettingsPage.test.jsx
  • src/pages/VisualizerApp.jsx
  • src/security/cspHeaders.test.js
  • src/services/accessService.js
  • src/services/waitlistService.js
  • src/services/waitlistService.test.js
  • supabase/functions/_shared/telegram.ts
  • supabase/functions/before-signup/index.ts
  • supabase/functions/delete-account/index.ts
  • supabase/functions/post-signup/index.ts
  • supabase/functions/waitlist-welcome/index.ts
  • supabase/migrations/20260710120000_platform_security_foundation.sql
  • supabase/migrations/20260710160000_drop_waitlist_pitch_variant.sql
  • supabase/migrations/20260715200000_add_welcomed_at_to_waitlist.sql
🚧 Files skipped from review as they are similar to previous changes (16)
  • supabase/functions/_shared/telegram.ts
  • src/services/accessService.js
  • src/pages/VisualizerApp.jsx
  • src/components/ProWaitlistBanner.jsx
  • src/pages/ProfileSettingsPage.test.jsx
  • .github/workflows/deploy-supabase-functions.yml
  • supabase/functions/post-signup/index.ts
  • src/pages/ProComingSoonPage.test.jsx
  • src/components/Footer.jsx
  • src/services/waitlistService.js
  • src/index.css
  • src/pages/ProfileSettingsPage.jsx
  • src/services/waitlistService.test.js
  • supabase/functions/delete-account/index.ts
  • supabase/migrations/20260710120000_platform_security_foundation.sql
  • src/contexts/AuthProvider.jsx
🛑 Comments failed to post (1)
src/security/cspHeaders.test.js (1)

10-10: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the unused expect import.

The expect function is no longer used because the test block relying on it was deleted. Removing it will resolve the static analysis warning.

♻️ Proposed fix
-import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { describe, it, vi, beforeEach } from 'vitest';
📝 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.

import { describe, it, vi, beforeEach } from 'vitest';
🧰 Tools
🪛 GitHub Check: Code Quality

[warning] 10-10:
'expect' is defined but never used. Allowed unused vars must match /^[A-Z_]|^motion$/u

🪛 GitHub Check: Upload PR preview

[warning] 10-10:
'expect' is defined but never used. Allowed unused vars must match /^[A-Z_]|^motion$/u

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/security/cspHeaders.test.js` at line 10, Remove the unused expect import
from the Vitest import declaration in the cspHeaders test file, while preserving
the remaining describe, it, vi, and beforeEach imports.

Source: Linters/SAST tools

The <main> element had sm:pt-20 (80px) while the header is only 56px
(h-14) and in normal document flow. This created 24px of dead space
between the header and content. Removed pt-0 sm:pt-20 since p-6
provides sufficient spacing.
Hide GitHub repo badge, language switcher, and theme toggle on pages
other than /app. These controls are auto-detected (browser language,
system theme) and can be changed from the visualizer. The sign-in
button remains visible everywhere; the user avatar is hidden when
authenticated on non-/app pages to reduce distraction.

- Header: gate GitHubRepoBadge, LanguageSwitcher, ThemeToggle behind isAppPage
- UserMenu: accept hideAvatar prop, return null when authenticated on non-/app
- Extract isAppPage from location.pathname for cleaner conditionals

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pages/VisualizerApp.jsx (1)

646-646: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Hide the waitlist banner in fullscreen mode.

Line 646 renders ProWaitlistBanner outside the isFullScreen conditional, so it remains visible while the fullscreen panel is active and consumes space above the h-screen visualizer. Render it only in normal mode, for example with {!isFullScreen && <ProWaitlistBanner source="app" />}.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/VisualizerApp.jsx` at line 646, Update the ProWaitlistBanner render
in VisualizerApp so it is conditional on !isFullScreen, keeping the banner
visible in normal mode while hiding it during fullscreen mode.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Line 47: Update the CI audit step to remove --ignore-registry-errors from the
pnpm audit command, ensuring registry failures remain visible and cause the
workflow gate to fail; alternatively, add a separate vulnerability scanner whose
result explicitly gates CI.

---

Outside diff comments:
In `@src/pages/VisualizerApp.jsx`:
- Line 646: Update the ProWaitlistBanner render in VisualizerApp so it is
conditional on !isFullScreen, keeping the banner visible in normal mode while
hiding it during fullscreen mode.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fbc2b594-523e-4150-95ea-29f2404c4a64

📥 Commits

Reviewing files that changed from the base of the PR and between 805eabb and 099ad23.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • src/pages/VisualizerApp.jsx

Comment thread .github/workflows/ci.yml Outdated
The insight panel backdrop used fixed inset-0 with no top offset,
covering the entire viewport including the header. On desktop, offset
the backdrop by 56px (header height) to match the PythonCodePanel
behavior. Mobile remains full-viewport since the panel sheets up from
the bottom.

- Add isMobile state with resize listener (matching PythonCodePanel)
- Apply style={{ top: '56px' }} to backdrop on desktop
The flag made pnpm audit exit 0 on registry non-200 responses, so the
audit gate could pass without scanning any advisories. Remove it so
registry failures are visible and the gate actually enforces audit
results.
pnpm audit is broken on pnpm 10.x because npm retired the legacy
audit endpoints (410 Gone). Switch to npm audit which uses the new
bulk advisory endpoint. Generates a temporary package-lock.json,
runs the audit, then cleans up.

Add comment explaining the workaround for future maintainers.
pnpm audit is broken on pnpm 10.x — npm retired the legacy audit
endpoints (410 Gone). Replace the fragile npm audit workaround with
OSV-Scanner, a standalone vulnerability scanner that reads
pnpm-lock.yaml natively and aggregates 30+ advisory sources.

- Remove npm audit workaround from ci.yml quality job
- Add .github/workflows/osv-scanner.yml with two jobs:
  - scan-pr: incremental PR scan (blocks on new vulns)
  - scan-scheduled: full scan on push/schedule (advisory only)
- Pin reusable workflows to SHA 9a49870 (v2.3.8, verified)
- Add osv-scanner.toml with empty ignore list for future triage
The reusable workflows require actions:read, contents:read, and
security-events:write but the caller didn't grant them, causing a
startup failure on the first run.
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

The scan completes successfully but the JSON export exceeds GitHub's
1MB job output limit. Disable export-results since SARIF upload to
Code Scanning is the primary integration, not job outputs.
The PR reusable workflow at this SHA doesn't expose export-results.
The default is already false, so no input is needed.
At v2.3.8 SHA (9a49870), the PR reusable workflow lacks the
export-results input — the export step runs unconditionally and
dumps full scan JSON into job outputs, exceeding GitHub's 1MB limit.

Track @main which has export-results support, and explicitly disable
it. Pin to a specific SHA once a release ships with this input.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Workflows config documentation Improvements or additions to documentation style Improve styling, design, and animation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants