feat: adds turnstile to deploy-web auth pages#2421
Conversation
📝 WalkthroughWalkthroughAdds Cloudflare Turnstile client widget + server verifier, enforces captchaToken on auth endpoints and service methods, moves server-side config reads to Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User as User
participant AuthUI as AuthPage (client)
participant Turnstile as Turnstile widget
participant API as Password API (server)
participant Verifier as CaptchaVerifier (service)
participant CF as Cloudflare Turnstile
User->>AuthUI: Click Sign In / Sign Up
AuthUI->>Turnstile: renderAndWaitResponse()
Turnstile->>CF: widget loads & user completes captcha
CF-->>Turnstile: returns token
Turnstile-->>AuthUI: resolves token
AuthUI->>API: POST /password-login or /password-signup {..., captchaToken}
API->>Verifier: verifyCaptcha(captchaToken, ctx)
Verifier->>CF: POST /siteverify {secret, response, remoteip?}
CF-->>Verifier: {success: boolean, error-codes?}
alt success
Verifier-->>API: Ok
API->>Auth Service: proceed with auth (login/signup)
API-->>AuthUI: 200 / set-cookie
else failure
Verifier-->>API: Err
API-->>AuthUI: 400 (captcha failure)
end
sequenceDiagram
autonumber
participant User as User
participant AuthUI as AuthPage
participant Form as ForgotPasswordForm
participant Turnstile as Turnstile widget
participant API as SendPasswordResetEmail API
participant Verifier as CaptchaVerifier
participant CF as Cloudflare Turnstile
User->>AuthUI: Select "Forgot password"
AuthUI->>Form: show forgot view
User->>Turnstile: complete captcha
Turnstile-->>Form: token
Form->>API: POST /send-password-reset-email {email, captchaToken}
API->>Verifier: verifyCaptcha(...)
Verifier->>CF: POST /siteverify {secret, response, remoteip?}
CF-->>Verifier: {success: boolean, error-codes?}
alt verified
API->>Service: send reset email
API-->>Form: 204 No Content
else failed
API-->>Form: 400 (captcha verification failed)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2421 +/- ##
==========================================
- Coverage 51.22% 50.96% -0.27%
==========================================
Files 1071 1062 -9
Lines 29354 29044 -310
Branches 6450 6431 -19
==========================================
- Hits 15038 14802 -236
- Misses 13898 13900 +2
+ Partials 418 342 -76
*This pull request uses carry forward flags. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/deploy-web/src/pages/api/github/authenticate.ts (1)
16-18: Remove unsafe type assertions.The type assertions
as stringon lines 16-17 bypass TypeScript's type safety. Line 18 (NEXT_PUBLIC_REDIRECT_URI) is used without a cast, creating an inconsistency. If these values can be undefined, validate them at runtime instead of using type assertions.🔎 Proposed fix
- const gitHubAuth = new GitHubAuth( - NEXT_PUBLIC_GITHUB_CLIENT_ID as string, - GITHUB_CLIENT_SECRET as string, - NEXT_PUBLIC_REDIRECT_URI, - services.externalApiHttpClient - ); + if (!NEXT_PUBLIC_GITHUB_CLIENT_ID || !GITHUB_CLIENT_SECRET || !NEXT_PUBLIC_REDIRECT_URI) { + return res.status(500).json({ error: "GitHub authentication is not configured" }); + } + const gitHubAuth = new GitHubAuth( + NEXT_PUBLIC_GITHUB_CLIENT_ID, + GITHUB_CLIENT_SECRET, + NEXT_PUBLIC_REDIRECT_URI, + services.externalApiHttpClient + );Based on coding guidelines, TypeScript types should be properly defined rather than using type assertions.
🧹 Nitpick comments (11)
apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx (1)
90-96: Consider using a button element instead of Link for better semantics.Next.js
Linkis designed for route navigation, but this element triggers a handler without navigation. A button styled as a link would be more semantically appropriate and eliminate the need forhref="#"andpreventDefault().🔎 Alternative implementation using a button
- <d.Link - className="text-xs text-current underline hover:no-underline" - prefetch={false} - href="#" - onClick={onForgotPasswordClick} - tabIndex={-1} - > + <button + type="button" + className="text-xs text-current underline hover:no-underline bg-transparent border-0 cursor-pointer p-0" + onClick={onForgotPasswordClick} + > Forgot password? - </d.Link> + </button>apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (1)
9-9: Consider using handler name reference instead of hardcoded string.The root describe block uses a hardcoded string literal. Per coding guidelines, using
proxyHandler.nameenables automated refactoring tools to find all references.🔎 Proposed refactor
-describe("proxy API handler", () => { +describe(proxyHandler.name, () => {As per coding guidelines, use
<Subject>.namein the root describe suite description.apps/deploy-web/env/.env.sample (1)
48-53: Consider alphabetical ordering of environment variables.Static analysis suggests
E2E_TESTING_CLIENT_TOKENshould appear beforeNEXT_PUBLIC_*variables for consistency with typical env file ordering conventions.🔎 Proposed reordering
UNLEASH_SERVER_API_TOKEN= +E2E_TESTING_CLIENT_TOKEN=any-random-string + NEXT_PUBLIC_TURNSTILE_ENABLED=true # https://developers.cloudflare.com/turnstile/troubleshooting/testing/#dummy-sitekeys-and-secret-keys NEXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA -E2E_TESTING_CLIENT_TOKEN=any-random-stringapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx (1)
62-62: Positional button selector is fragile.Using
getAllByRole("button")[0]relies on DOM order. Consider adding accessible names or data-testid attributes to buttons for more robust selection.apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
38-41: Dual ref pattern with fallback.The component accepts both a forwarded
refand an explicitturnstileRefprop, usingref || externalTurnstileRefinuseImperativeHandle. This works but is unconventional—consider documenting why both are needed or simplifying to use only the forwarded ref.apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (1)
244-251: Consider extracting TurnstileMock for reusability.The
TurnstileMockimplementation is well-structured, but it may be useful in other test files that interact with Turnstile. Consider extracting it to a shared test utility.🔎 Suggested approach
Create a test utility file (e.g.,
@tests/unit/mocks/turnstile.mock.ts):import type { RefObject } from "react"; import type { TurnstileRef } from "@src/components/turnstile/Turnstile"; export function createTurnstileMock(token = "test-captcha-token") { return jest.fn(({ turnstileRef }: { turnstileRef?: RefObject<TurnstileRef> }) => { if (turnstileRef) { (turnstileRef as { current: TurnstileRef }).current = { renderAndWaitResponse: jest.fn().mockResolvedValue({ token }) }; } return null; }); }Then use it in tests:
const TurnstileMock = createTurnstileMock();apps/deploy-web/src/pages/api/auth/password-login.ts (1)
17-26: Use destructuredbodyconsistently.The handler destructures
bodyfromctx(line 18) and uses it forcaptchaToken(line 20), but then usesreq.bodyfor email and password (lines 24-25). For consistency, use the destructuredbodythroughout.🔎 Proposed fix
const result = await services.sessionService.signIn({ - email: req.body.email, - password: req.body.password + email: body.email, + password: body.password });apps/deploy-web/src/pages/api/auth/send-password-reset-email.ts (1)
15-22: Use destructuredbodyconsistently.The handler destructures
bodyfromctx(line 16) and uses it forcaptchaToken(line 19), but then usesreq.body.email(line 22). For consistency, use the destructuredbodythroughout.🔎 Proposed fix
- const result = await services.sessionService.sendPasswordResetEmail({ email: req.body.email }); + const result = await services.sessionService.sendPasswordResetEmail({ email: body.email });apps/deploy-web/src/pages/api/auth/password-signup.ts (1)
39-48: Use destructuredbodyconsistently.The handler destructures
bodyfromctx(line 40) and uses it forcaptchaToken(line 42), but then usesreq.bodyfor email and password (lines 46-47). For consistency, use the destructuredbodythroughout.🔎 Proposed fix
const result = await services.sessionService.signUp({ - email: req.body.email, - password: req.body.password + email: body.email, + password: body.password });apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (1)
27-32: Consider adding truthy checks before type casting.Lines 28-29 cast header values to
stringwithout verifying they exist. While this works (returningundefinedwhen the header is missing), it's clearer to add truthy checks for consistency with thetypeofcheck on line 30.🔎 Proposed fix
function getRemoteIp(req: IncomingMessage) { - if (req.headers["cf-connecting-ip"]) return req.headers["cf-connecting-ip"] as string; - if (req.headers["x-real-ip"]) return req.headers["x-real-ip"] as string; + const cfConnectingIp = req.headers["cf-connecting-ip"]; + if (cfConnectingIp) return Array.isArray(cfConnectingIp) ? cfConnectingIp[0] : cfConnectingIp; + + const xRealIp = req.headers["x-real-ip"]; + if (xRealIp) return Array.isArray(xRealIp) ? xRealIp[0] : xRealIp; + if (typeof req.headers["x-forwarded-for"] === "string") return req.headers["x-forwarded-for"].split(",")[0]?.trim(); return req.socket?.remoteAddress; }Note: Headers can be arrays when multiple values are present. The fix handles both string and array cases.
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
82-104: AddresetMutationstosetActiveViewdependencies.The
setActiveViewcallback (line 87) callsresetMutations, butresetMutationsis not included in its dependency array (line 90). This could cause stale closures.🔎 Proposed fix
const setActiveView = useCallback( (value: string) => { const tabId = value !== "login" && value !== "signup" && value !== "forgot-password" ? "login" : value; const newSearchParams = new URLSearchParams(searchParams); newSearchParams.set("tab", tabId); resetMutations(); router.replace(`?${newSearchParams.toString()}`, undefined, { shallow: true }); }, - [searchParams, router] + [searchParams, router, resetMutations] );
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (36)
apps/deploy-web/env/.env.sampleapps/deploy-web/playwright.config.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsxapps/deploy-web/src/components/auth/SignInForm/SignInForm.tsxapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.tsxapps/deploy-web/src/config/env-config.schema.tsapps/deploy-web/src/hooks/useInjectedConfig.spec.tsapps/deploy-web/src/hooks/useInjectedConfig.tsapps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/middleware/verify-captcha/verify-captcha.tsapps/deploy-web/src/pages/_app.tsxapps/deploy-web/src/pages/api/auth/[...auth0].tsapps/deploy-web/src/pages/api/auth/password-login.tsapps/deploy-web/src/pages/api/auth/password-signup.tsapps/deploy-web/src/pages/api/auth/send-password-reset-email.tsapps/deploy-web/src/pages/api/auth/signup.tsapps/deploy-web/src/pages/api/bitbucket/authenticate.tsapps/deploy-web/src/pages/api/bitbucket/refresh.tsapps/deploy-web/src/pages/api/github/authenticate.tsapps/deploy-web/src/pages/api/gitlab/authenticate.tsapps/deploy-web/src/pages/api/gitlab/refresh.tsapps/deploy-web/src/pages/api/proxy/[...path].tsapps/deploy-web/src/pages/profile/[username]/index.tsxapps/deploy-web/src/pages/template/[id]/index.tsxapps/deploy-web/src/services/app-di-container/server-di-container.service.tsapps/deploy-web/src/services/auth/auth/auth.service.tsapps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.spec.tsapps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.tsapps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.tsapps/deploy-web/tests/ui/fixture/base-test.ts
💤 Files with no reviewable changes (5)
- apps/deploy-web/src/hooks/useInjectedConfig.spec.ts
- apps/deploy-web/src/pages/_app.tsx
- apps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.spec.ts
- apps/deploy-web/src/hooks/useInjectedConfig.ts
- apps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsxapps/deploy-web/playwright.config.tsapps/deploy-web/src/pages/api/bitbucket/authenticate.tsapps/deploy-web/src/pages/api/bitbucket/refresh.tsapps/deploy-web/src/pages/api/proxy/[...path].tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.tsapps/deploy-web/src/pages/api/gitlab/refresh.tsapps/deploy-web/src/pages/api/github/authenticate.tsapps/deploy-web/src/pages/api/auth/[...auth0].tsapps/deploy-web/src/pages/profile/[username]/index.tsxapps/deploy-web/src/services/auth/auth/auth.service.tsapps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.tsapps/deploy-web/src/middleware/verify-captcha/verify-captcha.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.tsapps/deploy-web/src/pages/api/auth/password-login.tsapps/deploy-web/src/config/env-config.schema.tsapps/deploy-web/src/pages/api/auth/signup.tsapps/deploy-web/src/pages/api/gitlab/authenticate.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/pages/api/auth/password-signup.tsapps/deploy-web/src/pages/template/[id]/index.tsxapps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.tsapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsxapps/deploy-web/src/components/turnstile/Turnstile.spec.tsxapps/deploy-web/src/services/app-di-container/server-di-container.service.tsapps/deploy-web/src/pages/api/auth/send-password-reset-email.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
{apps/deploy-web,apps/provider-console}/**/*.spec.tsx
📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)
Use
queryBymethods instead ofgetBymethods in test expectations
Files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
🧠 Learnings (10)
📚 Learning: 2025-11-25T17:45:44.790Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-11-25T17:45:44.790Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test
Applied to files:
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
📚 Learning: 2025-11-25T17:45:52.965Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-11-25T17:45:52.965Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files. The `setup` function must be at the bottom of the root `describe` block, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
Applied to files:
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
📚 Learning: 2025-11-19T15:15:07.283Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.283Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.
Applied to files:
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
📚 Learning: 2025-08-12T13:52:38.708Z
Learnt from: stalniy
Repo: akash-network/console PR: 1800
File: apps/deploy-web/next.config.js:163-165
Timestamp: 2025-08-12T13:52:38.708Z
Learning: In the Akash Console project, akashnetwork/env-loader is used at the top of next.config.js files to automatically load environment variables from env/.env files into process.env. SENTRY_ORG and SENTRY_PROJECT are stored as public configuration values in apps/deploy-web/env/.env and are loaded this way, while only SENTRY_AUTH_TOKEN is handled as a GitHub secret in workflows.
Applied to files:
apps/deploy-web/env/.env.sampleapps/deploy-web/src/config/env-config.schema.ts
📚 Learning: 2025-11-25T17:45:49.180Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-11-25T17:45:49.180Z
Learning: Applies to {apps/deploy-web,apps/provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
📚 Learning: 2025-07-11T10:46:43.711Z
Learnt from: stalniy
Repo: akash-network/console PR: 1660
File: apps/deploy-web/src/components/alerts/DeploymentAlertsContainer/DeploymentAlertsContainer.spec.tsx:54-56
Timestamp: 2025-07-11T10:46:43.711Z
Learning: In apps/{deploy-web,provider-console}/**/*.spec.tsx files: Use `getBy` methods instead of `queryBy` methods when testing element presence with `toBeInTheDocument()` because `getBy` throws an error and shows DOM state when element is not found, providing better debugging information than `queryBy` which returns null.
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-05-22T14:25:01.336Z
Learnt from: stalniy
Repo: akash-network/console PR: 1353
File: apps/deploy-web/src/config/browser-env.config.ts:0-0
Timestamp: 2025-05-22T14:25:01.336Z
Learning: For the `__AK_INJECTED_CONFIG__` global window property in the Akash Network Console, security is handled through cryptographic signature verification using a public key rather than property protection mechanisms like Object.defineProperty.
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts
📚 Learning: 2025-11-25T17:45:58.258Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/test-descriptions.mdc:0-0
Timestamp: 2025-11-25T17:45:58.258Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `<Subject>.name` in the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx
📚 Learning: 2025-09-10T08:40:53.104Z
Learnt from: stalniy
Repo: akash-network/console PR: 1892
File: apps/deploy-web/src/components/new-deployment/BidCountdownTimer.tsx:20-31
Timestamp: 2025-09-10T08:40:53.104Z
Learning: In TanStack Query v5, the onSuccess and onError callbacks were removed from useQuery options. Instead, use useEffect with the data as a dependency to handle side effects when query data changes.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
🧬 Code graph analysis (24)
apps/deploy-web/src/pages/api/bitbucket/authenticate.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/pages/api/bitbucket/refresh.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/pages/api/proxy/[...path].ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.ts (1)
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (1)
TurnstileVerifierService(5-56)
apps/deploy-web/src/pages/api/gitlab/refresh.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/pages/api/github/authenticate.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/pages/api/auth/[...auth0].ts (3)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)apps/deploy-web/src/services/app-di-container/browser-di-container.ts (1)
services(24-59)apps/deploy-web/src/services/auth/auth/rewrite-local-redirect.ts (1)
rewriteLocalRedirect(5-15)
apps/deploy-web/src/pages/profile/[username]/index.tsx (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (2)
apps/deploy-web/src/lib/nextjs/defineServerSideProps/defineServerSideProps.ts (1)
AppTypedContext(24-31)apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/tests/ui/fixture/base-test.ts (1)
apps/deploy-web/tests/ui/fixture/test-env.config.ts (1)
testEnvConfig(16-21)
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (1)
apps/deploy-web/src/pages/api/proxy/[...path].ts (1)
config(59-64)
apps/deploy-web/src/pages/api/auth/password-login.ts (2)
apps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.ts (1)
defineApiHandler(13-57)apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (1)
verifyCaptcha(6-25)
apps/deploy-web/src/pages/api/auth/signup.ts (2)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)apps/deploy-web/src/services/auth/auth/rewrite-local-redirect.ts (1)
rewriteLocalRedirect(5-15)
apps/deploy-web/src/pages/api/gitlab/authenticate.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (2)
apps/deploy-web/tests/ui/fixture/base-test.ts (1)
expect(15-15)apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
TurnstileRef(26-28)
apps/deploy-web/src/pages/api/auth/password-signup.ts (1)
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (1)
verifyCaptcha(6-25)
apps/deploy-web/src/pages/template/[id]/index.tsx (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts (1)
apps/deploy-web/src/config/env-config.schema.ts (1)
BrowserEnvConfig(78-78)
apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsx (1)
apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.tsx (1)
TrendIndicatorProps(14-19)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts (1)
getInjectedConfig(3-5)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (2)
apps/api/test/services/mock-config.service.ts (1)
mockConfig(10-17)apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (2)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (2)
ClientOnlyTurnstile(158-158)TurnstileRef(26-28)apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
useServices(33-35)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (1)
TurnstileVerifierService(5-56)
apps/deploy-web/src/pages/api/auth/send-password-reset-email.ts (2)
apps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.ts (1)
defineApiHandler(13-57)apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (1)
verifyCaptcha(6-25)
🪛 dotenv-linter (4.0.0)
apps/deploy-web/env/.env.sample
[warning] 53-53: [UnorderedKey] The E2E_TESTING_CLIENT_TOKEN key should go before the NEXT_PUBLIC_TURNSTILE_ENABLED key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (26)
apps/deploy-web/src/pages/api/proxy/[...path].ts (1)
41-41: LGTM! Configuration migration to privateConfig.The change correctly migrates the network ID configuration source from
services.configtoservices.privateConfig, which is a good security practice for server-side configuration management. The proxy target URL resolution logic remains unchanged.apps/deploy-web/src/services/auth/auth/auth.service.ts (1)
32-37: LGTM! Server-side captcha validation and error handling properly implemented.The captchaToken parameter is correctly added to all three authentication methods with proper TypeScript typing (no
anytypes). All three endpoints (/api/auth/password-login,/api/auth/password-signup,/api/auth/send-password-reset-email) implement server-side validation via theverifyCaptchamiddleware, which returns a 400 status code with a clear error message ("Captcha verification failed. Please try again.") when verification fails. The UI properly integrates captcha via the Turnstile component and error handling is managed through the RemoteApiError component in the mutation handlers.apps/deploy-web/tests/ui/fixture/base-test.ts (1)
15-15: LGTM! Convenience export.Exposing
expectas a named export is a helpful convenience for test files.apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsx (1)
118-119: Theas unknown asdouble cast pattern is necessary and appropriate here. TypeScript's strict mode requires this pattern when types have incompatible structures—the mock functions returning JSX don't structurally match the expectedtypeof COMPONENTStype. This pattern is established throughout the codebase and is explicitly validated as necessary in strict mode TypeScript.The original review's suggested fix using
(props: any)contradicts the stated guideline against usingany, making it an invalid suggestion. The current implementation is correct and should remain unchanged.apps/deploy-web/src/pages/api/gitlab/refresh.ts (1)
14-15: Config migration looks correct.The switch to
services.privateConfigaligns with the broader security improvement to source credentials from private config. The type assertions are consistent with other authentication handlers in this PR.apps/deploy-web/src/pages/api/bitbucket/authenticate.ts (1)
14-15: Config migration is correct.The switch to
privateConfigis consistent with the security improvements across auth handlers.apps/deploy-web/src/pages/api/bitbucket/refresh.ts (1)
14-15: Config migration is consistent with other Bitbucket handlers.The switch to
privateConfigcorrectly aligns with the authenticate endpoint.apps/deploy-web/src/pages/api/gitlab/authenticate.ts (1)
14-20: Config migration looks good.The switch to
privateConfigis consistent with the refresh endpoint and other OAuth handlers in this PR.apps/deploy-web/src/config/env-config.schema.ts (1)
67-76: Well-structured schema additions.Good documentation linking to Cloudflare's test key reference. The default bypass key facilitates local development while the required error message for
E2E_TESTING_CLIENT_TOKENprovides clear guidance.apps/deploy-web/src/components/turnstile/Turnstile.spec.tsx (2)
97-152: Good test coverage forrenderAndWaitResponse.The tests properly cover both the success and error paths with appropriate async handling using
actand event triggering.
155-176: Setup function follows guidelines correctly.The
setupfunction is positioned at the bottom of the describe block, accepts a single parameter with inline type definition, avoids shared state, and has no explicit return type. As per coding guidelines, this is the expected pattern.apps/deploy-web/src/components/turnstile/Turnstile.tsx (2)
115-115: Injected config takes precedence over prop.The
injectedConfig?.NEXT_PUBLIC_TURNSTILE_SITE_KEY ?? siteKeypattern means runtime-injected config overrides the explicitly passedsiteKeyprop. Verify this precedence is intentional—typically props would take priority.
158-158: Dynamic import returns component directly.The dynamic import pattern
dynamic(async () => Turnstile, ...)works but the more common pattern isdynamic(() => Promise.resolve({ default: Turnstile }), ...)or exporting the component as default from a separate file. Current approach works with Next.js 14.apps/deploy-web/src/pages/template/[id]/index.tsx (1)
38-38: LGTM!The config migration from
services.configtoservices.privateConfigis consistent with the broader refactoring in this PR.apps/deploy-web/src/pages/profile/[username]/index.tsx (1)
28-28: LGTM!The config migration from
services.configtoservices.privateConfigis consistent with the broader refactoring in this PR.apps/deploy-web/src/pages/api/auth/signup.ts (1)
12-13: LGTM!The config migration from
services.configtoservices.privateConfigis consistent with the broader refactoring in this PR. TherewriteLocalRedirectfunction signature correctly expects the privateConfig type.Also applies to: 23-23
apps/deploy-web/src/pages/api/auth/[...auth0].ts (1)
27-28: LGTM!The config migration from
services.configtoservices.privateConfigis consistently applied across all usage points in this auth handler.Also applies to: 47-47, 64-64
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (2)
115-118: LGTM!The test expectations correctly verify that
captchaTokenis included in both login and signup calls, aligning with the Turnstile integration.Also applies to: 176-179
216-274: LGTM!The test setup function follows all coding guidelines: positioned at the bottom of the describe block, accepts an inline parameter type, avoids shared state, and has no explicit return type annotation.
Based on coding guidelines for test files.
apps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.ts (1)
18-20: LGTM! Method guard implementation is correct.The early method validation with a 405 response follows the fail-fast principle and properly enforces HTTP method constraints before any request processing.
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.ts (1)
76-86: LGTM! Test structure follows coding guidelines.The test suite correctly uses
TurnstileVerifierService.namein the root describe, method name in nested describe, present simple 3rd person for test descriptions, andjest-mock-extendedfor mocking. The setup function is properly positioned at the bottom.apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
34-60: LGTM! Configuration migration and Turnstile integration are well-structured.The introduction of
privateConfigproperly separates sensitive server-side configuration (Auth0 credentials, Turnstile keys) from public config. ThecaptchaVerifieris correctly wired with the required dependencies and configuration.apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
230-235: LGTM! Turnstile integration is properly implemented.The Turnstile component is correctly configured with the ref for imperative API access, config-driven enabled flag and site key, and appropriate callback for resetting mutations.
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (3)
42-47: Consider handling network and 5xx failures within the Result type.Currently, 5xx responses and network failures will throw exceptions that propagate to the caller. Per Cloudflare's API, verification failures return 200 with
success: false, so 5xx indicates infrastructure issues. If the caller expects all outcomes via theResulttype, unhandled exceptions could be unexpected.If this is intentional (letting callers handle infrastructure errors separately), the current approach is acceptable. Otherwise, consider wrapping the POST call in a try-catch to return an
Errfor such cases.
58-71: Well-structured response interface.The
TurnstileVerifyResponseinterface properly models Cloudflare's verification response with comprehensive error code types. This provides good type safety for handling various verification failure scenarios.
73-83: Clear configuration interface with helpful documentation.The config interface is well-documented with references to Cloudflare's testing documentation for the bypass mechanism. This makes the E2E testing support explicit and maintainable.
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (1)
9-9: Consider usingproxyHandler.namein the describe block.As per coding guidelines, use
<Subject>.nameinstead of hardcoded strings to enable automated refactoring tools. However, sinceproxyHandleris a default export, verify that its.nameproperty is reliable before making this change.🔎 Proposed refactor (verify name property first)
-describe("proxy API handler", () => { +describe(proxyHandler.name || "proxy API handler", () => {Based on coding guidelines for test descriptions.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/deploy-web/playwright.config.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/tests/ui/fixture/test-env.config.ts
💤 Files with no reviewable changes (1)
- apps/deploy-web/tests/ui/fixture/test-env.config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/deploy-web/tests/ui/fixture/base-test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/playwright.config.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
🧠 Learnings (5)
📚 Learning: 2025-11-25T17:45:44.790Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-11-25T17:45:44.790Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test
Applied to files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
📚 Learning: 2025-11-19T15:15:07.283Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.283Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.
Applied to files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
📚 Learning: 2025-11-25T17:45:49.180Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-11-25T17:45:49.180Z
Learning: Applies to {apps/deploy-web,apps/provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations
Applied to files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
📚 Learning: 2025-11-25T17:45:52.965Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-11-25T17:45:52.965Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files. The `setup` function must be at the bottom of the root `describe` block, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
Applied to files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
📚 Learning: 2025-11-25T17:45:58.258Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/test-descriptions.mdc:0-0
Timestamp: 2025-11-25T17:45:58.258Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `<Subject>.name` in the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Applied to files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
🧬 Code graph analysis (1)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (2)
apps/api/test/services/mock-config.service.ts (1)
mockConfig(10-17)apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (1)
33-33: LGTM! Property name mismatch resolved.The changes correctly address the previous review comment by:
- Creating the mock as
services.privateConfig(line 33)- Assigning it to the
privateConfigproperty (line 77)- Using
satisfiesinstead ofas unknown asfor better type safety (line 79)The mock structure now accurately reflects the production DI container where the property is named
privateConfig.Also applies to: 77-77, 79-79
apps/deploy-web/playwright.config.ts (2)
7-11: Runtime guard improves test reliability but localhost check could be more robust.The guard successfully addresses the previous concern about missing token enforcement. However, the localhost bypass only matches the string "localhost" and won't recognize other local addresses like "127.0.0.1", "0.0.0.0", or "[::1]". Developers using IP-based local URLs would be required to set the token even for local testing.
Consider verifying that the localhost bypass aligns with backend behavior and optionally making the check more inclusive.
🔎 Optional enhancement to recognize additional local addresses
-if (!process.env.E2E_TESTING_CLIENT_TOKEN && !process.env.BASE_URL?.includes("localhost")) { +const isLocalUrl = process.env.BASE_URL?.match(/localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\]/); +if (!process.env.E2E_TESTING_CLIENT_TOKEN && !isLocalUrl) { throw new Error( "E2E_TESTING_CLIENT_TOKEN is a required env variable. Without it, tests will be blocked by captcha verification. Should be set to the same value as app's E2E_TESTING_CLIENT_TOKEN env variable." ); }
36-38: LGTM! Header configuration aligns with runtime guard.The
extraHTTPHeadersconfiguration correctly pairs with the runtime guard above. The fallback to an empty string is now only used for localhost environments (where the guard allows missing tokens), making this intentional rather than an oversight. This addresses the previous review concern about unintentional empty tokens causing test failures.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
38-42: LGTM! Icon dependencies refactored for testability.Moving icon references into the DEPENDENCIES object improves testability by allowing tests to mock these components if needed.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx
{apps/deploy-web,apps/provider-console}/**/*.spec.tsx
📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)
Use
queryBymethods instead ofgetBymethods in test expectations
Files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx
🧠 Learnings (6)
📚 Learning: 2025-11-25T17:45:44.790Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-11-25T17:45:44.790Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx
📚 Learning: 2025-11-25T17:45:52.965Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-11-25T17:45:52.965Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files. The `setup` function must be at the bottom of the root `describe` block, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx
📚 Learning: 2025-12-26T20:05:53.126Z
Learnt from: stalniy
Repo: akash-network/console PR: 2421
File: apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx:90-96
Timestamp: 2025-12-26T20:05:53.126Z
Learning: In the SignInForm component (apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx), the "Forgot password?" link intentionally uses tabIndex={-1} to keep it out of the keyboard tab order between email and password fields, ensuring a smooth tab flow through the form inputs without interruption.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
📚 Learning: 2025-11-25T17:45:58.258Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/test-descriptions.mdc:0-0
Timestamp: 2025-11-25T17:45:58.258Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `<Subject>.name` in the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx
📚 Learning: 2025-07-11T10:46:43.711Z
Learnt from: stalniy
Repo: akash-network/console PR: 1660
File: apps/deploy-web/src/components/alerts/DeploymentAlertsContainer/DeploymentAlertsContainer.spec.tsx:54-56
Timestamp: 2025-07-11T10:46:43.711Z
Learning: In apps/{deploy-web,provider-console}/**/*.spec.tsx files: Use `getBy` methods instead of `queryBy` methods when testing element presence with `toBeInTheDocument()` because `getBy` throws an error and shows DOM state when element is not found, providing better debugging information than `queryBy` which returns null.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx
📚 Learning: 2025-09-10T08:40:53.104Z
Learnt from: stalniy
Repo: akash-network/console PR: 1892
File: apps/deploy-web/src/components/new-deployment/BidCountdownTimer.tsx:20-31
Timestamp: 2025-09-10T08:40:53.104Z
Learning: In TanStack Query v5, the onSuccess and onError callbacks were removed from useQuery options. Instead, use useEffect with the data as a dependency to handle side effects when query data changes.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
🧬 Code graph analysis (2)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (4)
apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx (2)
SignInForm(38-123)DEPENDENCIES(27-36)apps/deploy-web/tests/unit/mocks.tsx (1)
ComponentMock(6-8)apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
DEPENDENCIES(25-46)apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
TurnstileRef(26-28)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (2)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (2)
ClientOnlyTurnstile(158-158)TurnstileRef(26-28)apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
useServices(33-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (18)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (6)
115-118: LGTM! Test correctly verifies captcha token inclusion.The test now properly asserts that the captcha token is included in the login payload, ensuring the Turnstile integration works as expected.
176-179: LGTM! Test correctly verifies captcha token inclusion.The test now properly asserts that the captcha token is included in the signup payload, ensuring the Turnstile integration works as expected.
216-256: LGTM! Comprehensive test coverage for forgot password flow.The new test suite properly covers:
- Rendering the forgot password form when requested from SignInForm
- Submitting the form with captchaToken included in the request
The test structure follows established patterns and coding guidelines.
267-273: LGTM! Router mock enhancement enables URL change verification.The enhanced router mock now captures URL updates through
replaceand exposes them viasetRouterPageParams, enabling tests to verify routing behavior with updated search parameters.
290-294: LGTM! Stateful search params mock enables dynamic testing.The stateful mock using
useStateallows tests to simulate search parameter changes, which is necessary for verifying the forgot password flow and tab switching behavior.
296-303: LGTM! Turnstile mock properly simulates captcha behavior.The mock correctly:
- Sets up the
turnstileRef.currentwith arenderAndWaitResponsemethod- Returns the test captcha token consistently across all test scenarios
- Enables verification of captcha integration without external dependencies
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (12)
3-3: LGTM! useRef import needed for Turnstile integration.The
useRefhook is properly imported for managing the Turnstile component reference.
14-15: LGTM! Turnstile imports properly added.The
TurnstileReftype andClientOnlyTurnstilecomponent are correctly imported for the captcha integration.
33-33: LGTM! Turnstile added to public dependencies.Adding
Turnstile: ClientOnlyTurnstileto the DEPENDENCIES object makes the component testable by allowing test files to inject mocks.
53-53: LGTM! appConfig retrieved for Turnstile configuration.The
appConfigis properly retrieved from services to access Turnstile configuration values (site key and enabled flag).
58-58: LGTM! Turnstile ref properly initialized.The
turnstileRefis correctly initialized withuseRef<TurnstileRef | null>(null)to manage the Turnstile component instance.
69-71: LGTM! Proper guard for captcha availability.The guard ensures that the Turnstile component has been rendered before attempting to retrieve a captcha token, preventing runtime errors.
74-74: LGTM! Captcha token retrieval implemented correctly.The captcha token is properly retrieved using the imperative
renderAndWaitResponse()API before proceeding with authentication.
77-79: LGTM! Captcha token passed to authentication methods.The
captchaTokenis correctly included in bothloginandsignupcalls, ensuring server-side verification.
92-92: LGTM! Mutations reset on view change.Calling
resetMutations()when changing views properly clears error states and ensures a clean UI transition.
99-103: LGTM! Forgot password flow includes captcha verification.The forgot password mutation correctly:
- Guards against missing Turnstile ref
- Retrieves captcha token
- Passes token to
sendPasswordResetEmail
106-109: LGTM! Reset mutations helper properly implemented.The
resetMutationscallback correctly resets bothsignInOrSignUpandforgotPasswordmutations to clear error states.
236-241: LGTM! Turnstile component properly integrated.The Turnstile component is correctly rendered with:
turnstileReffor imperative API accessenabledflag from configsiteKeyfrom configonGoBackcallback to reset mutations
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
67-84: Authentication will fail when Turnstile is disabled (NEXT_PUBLIC_TURNSTILE_ENABLED=false).The
signInOrSignUpandforgotPasswordmutations unconditionally throw "Captcha has not been rendered" whenturnstileRef.currentis null. Since the Turnstile component returns null when disabled (line 90-92 of Turnstile.tsx), the ref is never initialized, causing all authentication attempts to fail. TheauthService.login(),authService.signup(), andauthService.sendPasswordResetEmail()methods all requirecaptchaTokenas a mandatory parameter with no fallback mechanism.Provide a fallback token or conditionally bypass the Turnstile check when the feature is disabled.
🧹 Nitpick comments (1)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
86-96: AddresetMutationsto the dependency array.The
setActiveViewcallback callsresetMutations()on line 92 but doesn't include it in the dependency array on line 95. This violates React's exhaustive-deps rule and could lead to stale closure bugs.🔎 Proposed fix
const setActiveView = useCallback( (value: string) => { const tabId = value !== "login" && value !== "signup" && value !== "forgot-password" ? "login" : value; const newSearchParams = new URLSearchParams(searchParams); newSearchParams.set("tab", tabId); resetMutations(); router.replace(`?${newSearchParams.toString()}`, undefined, { shallow: true }); }, - [searchParams, router] + [searchParams, router, resetMutations] );
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
🧠 Learnings (3)
📚 Learning: 2025-12-26T20:05:53.126Z
Learnt from: stalniy
Repo: akash-network/console PR: 2421
File: apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx:90-96
Timestamp: 2025-12-26T20:05:53.126Z
Learning: In the SignInForm component (apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx), the "Forgot password?" link intentionally uses tabIndex={-1} to keep it out of the keyboard tab order between email and password fields, ensuring a smooth tab flow through the form inputs without interruption.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
📚 Learning: 2025-07-11T10:46:43.711Z
Learnt from: stalniy
Repo: akash-network/console PR: 1660
File: apps/deploy-web/src/components/alerts/DeploymentAlertsContainer/DeploymentAlertsContainer.spec.tsx:54-56
Timestamp: 2025-07-11T10:46:43.711Z
Learning: In apps/{deploy-web,provider-console}/**/*.spec.tsx files: Use `getBy` methods instead of `queryBy` methods when testing element presence with `toBeInTheDocument()` because `getBy` throws an error and shows DOM state when element is not found, providing better debugging information than `queryBy` which returns null.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
📚 Learning: 2025-09-10T08:40:53.104Z
Learnt from: stalniy
Repo: akash-network/console PR: 1892
File: apps/deploy-web/src/components/new-deployment/BidCountdownTimer.tsx:20-31
Timestamp: 2025-09-10T08:40:53.104Z
Learning: In TanStack Query v5, the onSuccess and onError callbacks were removed from useQuery options. Instead, use useEffect with the data as a dependency to handle side effects when query data changes.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (7)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (7)
3-3: LGTM! Imports are correctly structured.The addition of
useRefand Turnstile-related imports follows TypeScript best practices with proper type vs. value import separation.Also applies to: 14-15
25-46: LGTM! Dependency injection pattern applied consistently.The addition of Turnstile and UI components to the DEPENDENCIES object maintains the testability pattern already established in this component.
53-53: LGTM! Proper initialization of Turnstile dependencies.The
appConfigandturnstileRefare correctly initialized with appropriate TypeScript types.Also applies to: 58-58
97-105: LGTM! Consistent captcha integration.The
forgotPasswordmutation correctly integrates captcha token retrieval, following the same pattern assignInOrSignUp. Ensure the disabled Turnstile scenario is handled (as noted in the previous comment).
106-109: LGTM! Mutation reset helper is correctly implemented.The
resetMutationshelper properly resets both mutations and can be reused across different flows.
119-119: LGTM! UI component references updated consistently.The changes to use dependency-injected component references (e.g.,
d.ZapIcon,d.AkashConsoleLogo) maintain consistency with the established pattern. The spacing adjustment on line 167 is appropriate.Also applies to: 128-128, 137-137, 151-151, 167-167, 212-212
235-240: LGTM! Turnstile component integration is well-structured.The Turnstile component receives all necessary props (ref, config flags, callback) and is properly positioned in the auth flow.
2612bcc to
282cf57
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/deploy-web/src/pages/api/github/authenticate.ts (1)
14-20: Type assertions bypass safety checks.The
as stringcasts on lines 16–17 violate the project guideline against type assertions and can cause runtime failures if environment variables are undefined.Replace assertions with explicit validation.
🔎 Suggested validation approach
async handler({ body, res, services }) { const { NEXT_PUBLIC_GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, NEXT_PUBLIC_REDIRECT_URI } = services.privateConfig; + + if (!NEXT_PUBLIC_GITHUB_CLIENT_ID || !GITHUB_CLIENT_SECRET || !NEXT_PUBLIC_REDIRECT_URI) { + return res.status(500).json({ error: "GitHub OAuth is not configured" }); + } + const gitHubAuth = new GitHubAuth( - NEXT_PUBLIC_GITHUB_CLIENT_ID as string, - GITHUB_CLIENT_SECRET as string, + NEXT_PUBLIC_GITHUB_CLIENT_ID, + GITHUB_CLIENT_SECRET, NEXT_PUBLIC_REDIRECT_URI, services.externalApiHttpClient ); const accessToken = await gitHubAuth.exchangeAuthorizationCodeForToken(body.code); res.status(200).json({ accessToken }); }apps/deploy-web/src/pages/api/gitlab/authenticate.ts (1)
14-20: Type assertions bypass safety checks.The
as stringcasts on lines 16–17 violate the project guideline against type assertions and can cause runtime failures if environment variables are undefined.Replace assertions with explicit validation.
🔎 Suggested validation approach
async handler({ body, res, services }) { const { NEXT_PUBLIC_GITLAB_CLIENT_ID, GITLAB_CLIENT_SECRET, NEXT_PUBLIC_REDIRECT_URI } = services.privateConfig; + + if (!NEXT_PUBLIC_GITLAB_CLIENT_ID || !GITLAB_CLIENT_SECRET || !NEXT_PUBLIC_REDIRECT_URI) { + return res.status(500).json({ error: "GitLab OAuth is not configured" }); + } + const gitlabAuth = new GitlabAuth( - NEXT_PUBLIC_GITLAB_CLIENT_ID as string, - GITLAB_CLIENT_SECRET as string, + NEXT_PUBLIC_GITLAB_CLIENT_ID, + GITLAB_CLIENT_SECRET, NEXT_PUBLIC_REDIRECT_URI, services.externalApiHttpClient ); const tokens = await gitlabAuth.exchangeAuthorizationCodeForTokens(body.code); res.status(200).json(tokens); }apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
87-96: MissingresetMutationsin dependency array causes stale closure.
setActiveViewcallsresetMutations()but doesn't include it in its dependency array. IfresetMutationsidentity changes (due to its own dependencies changing), this callback will call the stale version.🔎 Proposed fix
const setActiveView = useCallback( (value: string) => { const tabId = value !== "login" && value !== "signup" && value !== "forgot-password" ? "login" : value; const newSearchParams = new URLSearchParams(searchParams); newSearchParams.set("tab", tabId); resetMutations(); router.replace(`?${newSearchParams.toString()}`, undefined, { shallow: true }); }, - [searchParams, router] + [searchParams, router, resetMutations] );
♻️ Duplicate comments (2)
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts (1)
4-4: Avoid usinganytype (duplicate concern).The cast to
anyviolates the coding guideline. A proper interface declaration forwindow.__AK_INJECTED_CONFIG__should be defined instead.Based on coding guidelines for TypeScript.
apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
63-88: Stale closure and cleanup concerns were previously flagged.The past review already noted the stale closure on
status(line 80) and potential memory leak if the component unmounts before events fire.
🧹 Nitpick comments (6)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (1)
9-9: Consider using a named reference in the test suite description.The describe block uses a hardcoded string
"proxy API handler". Per coding guidelines, consider using a named reference (e.g.,proxyHandler.nameor extracting the handler to a named constant) to enable automated refactoring tools to find all references.🔎 Possible refactor
One approach is to extract the default export to a named constant:
In
apps/deploy-web/src/pages/api/proxy/[...path].ts:export const proxyApiHandler = defineApiHandler({ // ... existing configuration }); export default proxyApiHandler;Then in the test file:
-describe("proxy API handler", () => { +describe(proxyHandler.name, () => {As per coding guidelines, this improves maintainability but is not critical to functionality.
apps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.ts (1)
18-20: Efficient method guard placement.The early method check before session retrieval and schema validation is well-placed for efficiency.
Consider adding Allow header (optional)
Per HTTP spec, 405 responses should include an
Allowheader indicating permitted methods. This is optional but improves API discoverability:if (options.method && req.method !== options.method) { + res.setHeader("Allow", options.method); return res.status(405).json({ message: "Method not allowed" } as TResponse); }apps/deploy-web/src/pages/api/auth/send-password-reset-email.ts (1)
16-22: Inconsistent body access:body.captchaTokenvsreq.body.email.Line 19 uses the destructured
body.captchaTokenfrom the validated context, but line 22 usesreq.body.email. For consistency and to ensure you're using the validated data, preferbody.email.🔎 Proposed fix
- const result = await services.sessionService.sendPasswordResetEmail({ email: req.body.email }); + const result = await services.sessionService.sendPasswordResetEmail({ email: body.email });apps/deploy-web/src/components/turnstile/Turnstile.spec.tsx (2)
2-2: Useactfrom@testing-library/reactinstead of the deprecated import.The import from
react-dom/test-utilsis deprecated in React 18+. The@testing-library/reactpackage re-exportsactand is the recommended source.🔎 Proposed fix
-import { act } from "react-dom/test-utils"; +import { act, fireEvent, render, screen } from "@testing-library/react";And remove the duplicate import on line 11:
-import { fireEvent, render, screen } from "@testing-library/react";
62-62: Consider adding accessible names to buttons for more robust selectors.Using positional selectors like
getAllByRole("button")[0]andgetAllByRole("button")[1]is fragile—if button order changes, tests break silently. Consider addingaria-labelattributes to the component's Retry and Go Back buttons, then selecting by name:fireEvent.click(screen.getByRole("button", { name: /retry/i })); fireEvent.click(screen.getByRole("button", { name: /go back/i }));This would also improve accessibility of the actual component.
Also applies to: 89-89
apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
46-46: Minor:getInjectedConfig()is called on every render.This function reads from
windowon each render. Consider memoizing if performance becomes a concern, though the impact is likely negligible.🔎 Proposed fix
- const injectedConfig = getInjectedConfig(); + const injectedConfig = useMemo(() => getInjectedConfig(), []);
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (37)
apps/deploy-web/env/.env.sampleapps/deploy-web/playwright.config.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsxapps/deploy-web/src/components/auth/SignInForm/SignInForm.tsxapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.tsxapps/deploy-web/src/config/env-config.schema.tsapps/deploy-web/src/hooks/useInjectedConfig.spec.tsapps/deploy-web/src/hooks/useInjectedConfig.tsapps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/middleware/verify-captcha/verify-captcha.tsapps/deploy-web/src/pages/_app.tsxapps/deploy-web/src/pages/api/auth/[...auth0].tsapps/deploy-web/src/pages/api/auth/password-login.tsapps/deploy-web/src/pages/api/auth/password-signup.tsapps/deploy-web/src/pages/api/auth/send-password-reset-email.tsapps/deploy-web/src/pages/api/auth/signup.tsapps/deploy-web/src/pages/api/bitbucket/authenticate.tsapps/deploy-web/src/pages/api/bitbucket/refresh.tsapps/deploy-web/src/pages/api/github/authenticate.tsapps/deploy-web/src/pages/api/gitlab/authenticate.tsapps/deploy-web/src/pages/api/gitlab/refresh.tsapps/deploy-web/src/pages/api/proxy/[...path].tsapps/deploy-web/src/pages/profile/[username]/index.tsxapps/deploy-web/src/pages/template/[id]/index.tsxapps/deploy-web/src/services/app-di-container/server-di-container.service.tsapps/deploy-web/src/services/auth/auth/auth.service.tsapps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.spec.tsapps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.tsapps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/tests/ui/fixture/test-env.config.ts
💤 Files with no reviewable changes (6)
- apps/deploy-web/src/pages/_app.tsx
- apps/deploy-web/src/hooks/useInjectedConfig.spec.ts
- apps/deploy-web/src/hooks/useInjectedConfig.ts
- apps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.spec.ts
- apps/deploy-web/tests/ui/fixture/test-env.config.ts
- apps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.ts
🚧 Files skipped from review as they are similar to previous changes (11)
- apps/deploy-web/src/pages/api/gitlab/refresh.ts
- apps/deploy-web/src/pages/api/bitbucket/refresh.ts
- apps/deploy-web/src/config/env-config.schema.ts
- apps/deploy-web/src/pages/api/auth/[...auth0].ts
- apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.ts
- apps/deploy-web/playwright.config.ts
- apps/deploy-web/src/services/app-di-container/server-di-container.service.ts
- apps/deploy-web/src/pages/api/auth/password-signup.ts
- apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx
- apps/deploy-web/src/services/auth/auth/auth.service.ts
- apps/deploy-web/src/pages/api/auth/password-login.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/deploy-web/src/pages/api/auth/signup.tsapps/deploy-web/src/pages/api/proxy/[...path].tsapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/pages/api/bitbucket/authenticate.tsapps/deploy-web/src/pages/api/gitlab/authenticate.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.tsapps/deploy-web/src/middleware/verify-captcha/verify-captcha.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsxapps/deploy-web/src/pages/template/[id]/index.tsxapps/deploy-web/src/components/turnstile/Turnstile.tsxapps/deploy-web/src/pages/profile/[username]/index.tsxapps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsxapps/deploy-web/src/pages/api/github/authenticate.tsapps/deploy-web/src/pages/api/auth/send-password-reset-email.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
{apps/deploy-web,apps/provider-console}/**/*.spec.tsx
📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)
Use
queryBymethods instead ofgetBymethods in test expectations
Files:
apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
🧠 Learnings (14)
📚 Learning: 2025-11-25T17:45:52.965Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-11-25T17:45:52.965Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files. The `setup` function must be at the bottom of the root `describe` block, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
📚 Learning: 2025-11-25T17:45:44.790Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-11-25T17:45:44.790Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
📚 Learning: 2025-12-26T20:06:01.746Z
Learnt from: stalniy
Repo: akash-network/console PR: 2421
File: apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx:90-96
Timestamp: 2025-12-26T20:06:01.746Z
Learning: In the SignInForm component (apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx), the "Forgot password?" link intentionally uses tabIndex={-1} to keep it out of the keyboard tab order between email and password fields, ensuring a smooth tab flow through the form inputs without interruption.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
📚 Learning: 2025-11-25T17:45:58.258Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/test-descriptions.mdc:0-0
Timestamp: 2025-11-25T17:45:58.258Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `<Subject>.name` in the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
📚 Learning: 2025-07-11T10:46:43.711Z
Learnt from: stalniy
Repo: akash-network/console PR: 1660
File: apps/deploy-web/src/components/alerts/DeploymentAlertsContainer/DeploymentAlertsContainer.spec.tsx:54-56
Timestamp: 2025-07-11T10:46:43.711Z
Learning: In apps/{deploy-web,provider-console}/**/*.spec.tsx files: Use `getBy` methods instead of `queryBy` methods when testing element presence with `toBeInTheDocument()` because `getBy` throws an error and shows DOM state when element is not found, providing better debugging information than `queryBy` which returns null.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsxapps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-05-22T14:25:01.336Z
Learnt from: stalniy
Repo: akash-network/console PR: 1353
File: apps/deploy-web/src/config/browser-env.config.ts:0-0
Timestamp: 2025-05-22T14:25:01.336Z
Learning: For the `__AK_INJECTED_CONFIG__` global window property in the Akash Network Console, security is handled through cryptographic signature verification using a public key rather than property protection mechanisms like Object.defineProperty.
Applied to files:
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.tsapps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-11-25T17:45:39.561Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T17:45:39.561Z
Learning: Applies to **/*.{ts,tsx,js} : Never use type `any` or cast to type `any`. Always define the proper TypeScript types.
Applied to files:
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts
📚 Learning: 2025-10-31T11:26:42.138Z
Learnt from: stalniy
Repo: akash-network/console PR: 2138
File: apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts:379-382
Timestamp: 2025-10-31T11:26:42.138Z
Learning: In TypeScript/JavaScript, the pattern of checking a cached value and then performing an async operation to fetch it without proper synchronization is race condition unsafe:
```typescript
private async getAddress() {
if (!this.address) {
this.address = await this.wallet.getFirstAddress();
}
return this.address;
}
```
Multiple concurrent calls can all pass the `if (!this.address)` check before any of them sets the value, leading to duplicate async operations. This should be flagged as a race condition. Proper synchronization (mutex, atomic promise caching, or guaranteed single-threaded execution) is required.
Applied to files:
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.tsapps/deploy-web/src/components/turnstile/Turnstile.tsx
📚 Learning: 2025-11-25T17:45:39.561Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T17:45:39.561Z
Learning: Applies to **/*.{ts,tsx,js} : Never use deprecated methods from libraries.
Applied to files:
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts
📚 Learning: 2025-08-12T13:52:38.708Z
Learnt from: stalniy
Repo: akash-network/console PR: 1800
File: apps/deploy-web/next.config.js:163-165
Timestamp: 2025-08-12T13:52:38.708Z
Learning: In the Akash Console project, akashnetwork/env-loader is used at the top of next.config.js files to automatically load environment variables from env/.env files into process.env. SENTRY_ORG and SENTRY_PROJECT are stored as public configuration values in apps/deploy-web/env/.env and are loaded this way, while only SENTRY_AUTH_TOKEN is handled as a GitHub secret in workflows.
Applied to files:
apps/deploy-web/env/.env.sample
📚 Learning: 2025-09-10T08:40:53.104Z
Learnt from: stalniy
Repo: akash-network/console PR: 1892
File: apps/deploy-web/src/components/new-deployment/BidCountdownTimer.tsx:20-31
Timestamp: 2025-09-10T08:40:53.104Z
Learning: In TanStack Query v5, the onSuccess and onError callbacks were removed from useQuery options. Instead, use useEffect with the data as a dependency to handle side effects when query data changes.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
📚 Learning: 2025-11-25T17:45:49.180Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-11-25T17:45:49.180Z
Learning: Applies to {apps/deploy-web,apps/provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-11-19T15:15:07.283Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.283Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
🧬 Code graph analysis (16)
apps/deploy-web/src/pages/api/auth/signup.ts (2)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)apps/deploy-web/src/services/auth/auth/rewrite-local-redirect.ts (1)
rewriteLocalRedirect(5-15)
apps/deploy-web/src/pages/api/proxy/[...path].ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsx (1)
apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.tsx (1)
TrendIndicatorProps(14-19)
apps/deploy-web/src/pages/api/bitbucket/authenticate.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/pages/api/gitlab/authenticate.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (3)
apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx (2)
SignInForm(38-123)DEPENDENCIES(27-36)apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
DEPENDENCIES(25-46)apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
TurnstileRef(26-28)
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts (1)
apps/deploy-web/src/config/env-config.schema.ts (1)
BrowserEnvConfig(78-78)
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (2)
apps/deploy-web/src/lib/nextjs/defineServerSideProps/defineServerSideProps.ts (1)
AppTypedContext(24-31)apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (2)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (2)
ClientOnlyTurnstile(158-158)TurnstileRef(26-28)apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
useServices(33-35)
apps/deploy-web/src/pages/template/[id]/index.tsx (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts (1)
getInjectedConfig(3-5)
apps/deploy-web/src/pages/profile/[username]/index.tsx (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (2)
apps/api/test/services/mock-config.service.ts (1)
mockConfig(10-17)apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/turnstile/Turnstile.spec.tsx (1)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (2)
TurnstileRef(26-28)Turnstile(38-156)
apps/deploy-web/src/pages/api/github/authenticate.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/pages/api/auth/send-password-reset-email.ts (2)
apps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.ts (1)
defineApiHandler(13-57)apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (1)
verifyCaptcha(6-25)
🪛 dotenv-linter (4.0.0)
apps/deploy-web/env/.env.sample
[warning] 53-53: [UnorderedKey] The E2E_TESTING_CLIENT_TOKEN key should go before the NEXT_PUBLIC_TURNSTILE_ENABLED key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (18)
apps/deploy-web/src/pages/api/proxy/[...path].ts (1)
41-41: Configuration migration looks correct.The change from
services.configtoservices.privateConfigcorrectly aligns with the PR's objective of moving server configuration reads toprivateConfig. Theserver-di-container.service.tsconfirms thatprivateConfigis properly defined and containsNEXT_PUBLIC_MANAGED_WALLET_NETWORK_ID.apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (1)
33-33: Test configuration correctly updated to match production code.The changes successfully resolve the property name mismatch flagged in the previous review. Both the mock type (line 33) and the test object property (line 77) now correctly use
privateConfig, mirroring the structure inserver-di-container.service.ts.The change from
as unknown as typeof servicestosatisfies typeof serviceson line 79 is also a good improvement—satisfiesprovides stronger type checking while preserving the inferred type.Also applies to: 77-77, 79-79
apps/deploy-web/src/pages/template/[id]/index.tsx (1)
37-40: Configuration migration consistent with the codebase pattern.This change mirrors the migration in
apps/deploy-web/src/pages/profile/[username]/index.tsxand aligns with the server DI container configuration. The template fetching logic and authorization flow remain intact.apps/deploy-web/src/pages/profile/[username]/index.tsx (1)
27-29: Configuration migration is complete and consistent across server-side code.The change from
services.configtoservices.privateConfigforNEXT_PUBLIC_MANAGED_WALLET_NETWORK_IDis properly implemented. All server-side references useservices.privateConfig(including the template page, proxy route, and DI container), while client-side code correctly usesbrowserEnvConfig. The configuration is properly initialized in the server environment setup.apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsx (1)
118-119: This type cast pattern is appropriate and does not violate TypeScript guidelines. Theas unknown aspattern usesunknown(type-safe) rather thanany, which the coding guidelines specifically forbid. Double casts throughunknownare necessary when types are structurally incompatible, as is the case here: the mock is a function returning JSX while the actualGraphUpandGraphDownare icon components from the iconoir-react library. This pattern is established throughout the test suite and aligns with strict mode typing practices.Likely an incorrect or invalid review comment.
apps/deploy-web/src/pages/api/auth/signup.ts (1)
12-13: LGTM! Config access migrated to privateConfig.The migration from
services.configtoservices.privateConfigis consistent with the server-side configuration pattern established in the DI container.Also applies to: 23-23
apps/deploy-web/tests/ui/fixture/base-test.ts (1)
15-22: Clean implementation using Cloudflare's testing site key.The approach of injecting a frozen config with the always-pass Turnstile site key (
1x00000000000000000000AA) is well-aligned with Cloudflare's testing documentation. TheObject.freezeprevents accidental mutation during tests.The
(window as any)cast on line 17 is acceptable here since TypeScript doesn't provide native typing for custom window properties, and declaring a global augmentation for test-only code would be overkill.apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (2)
296-303: Well-implemented TurnstileMock with ref-based token injection.The mock correctly implements the
TurnstileRefinterface by assigning toturnstileRef.current, enabling the component under test to callrenderAndWaitResponse()and receive the test token. This approach follows the dependency injection pattern without usingjest.mock().
216-256: Comprehensive ForgotPassword workflow tests.The tests properly cover:
- Navigation from SignInForm to ForgotPasswordForm via
onForgotPasswordClick- Form submission with captchaToken verification
Using
getByTextfor presence assertions aligns with the project's testing guidelines for better error diagnostics.apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (2)
6-25: Clean CAPTCHA middleware implementation.The middleware correctly:
- Extracts client IP with proper priority for Cloudflare environments
- Passes bypass token for E2E testing support
- Logs verification failures before returning an error
- Uses
ts-resultsfor consistent error handlingThe integration with
AppTypedContextensures type safety for the services and request objects.
27-32: IP extraction handles common proxy headers correctly.The priority order (CF-Connecting-IP → X-Real-IP → X-Forwarded-For → socket) is appropriate for Cloudflare-fronted deployments. The optional return type aligns with the
remoteIp?: stringparameter in the verifier.apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (1)
42-47: No issue. The Cloudflare Turnstile siteverify endpoint accepts bothapplication/x-www-form-urlencodedandapplication/jsonper official documentation, so the implementation is correct.apps/deploy-web/src/components/turnstile/Turnstile.spec.tsx (2)
97-152: Well-structured tests for the imperative handle.The
renderAndWaitResponsetests properly verify both the success and error paths using the ref-based pattern. The use oftriggerSuccessandtriggerErrorclosures to simulate the underlying ReactTurnstile callbacks is a clean approach.
155-176: Setup function follows guidelines correctly.The setup function is positioned at the bottom of the describe block, accepts a single parameter with an inline type definition, avoids shared state, and has no explicit return type. Good adherence to the coding guidelines.
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (2)
67-84: Turnstile integration in mutation flow is well-implemented.The captcha token acquisition flow correctly:
- Guards against null ref before calling
renderAndWaitResponse- Awaits the token before proceeding with auth
- Passes the token to the service methods
235-240: Turnstile component wiring looks correct.The component is properly configured with the ref, enabled flag from config, site key, and the
onGoBackcallback to reset mutations when the user dismisses the captcha.apps/deploy-web/src/components/turnstile/Turnstile.tsx (2)
121-124: Theexpiredevent won't resolve or reject the pending promise.
onExpiredispatches an"expired"event, butrenderAndWaitResponseonly listens for"success"and"error". When a token expires, the promise remains pending whileuseWhenresets the widget for another attempt.If this is intentional (letting the user retry without the caller knowing), consider documenting this behavior. Otherwise, either:
- Dispatch
"error"instead of"expired"to reject the promise, or- Add an
"expired"listener inrenderAndWaitResponsethat rejects with a distinct reason.
38-41: Clean forwardRef implementation with imperative handle.The component correctly exposes
renderAndWaitResponseviaforwardRefanduseImperativeHandle, allowing parent components to trigger the captcha flow imperatively. The dual ref support (ref || externalTurnstileRef) provides flexibility for different usage patterns.Also applies to: 156-156
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts
Show resolved
Hide resolved
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts
Outdated
Show resolved
Hide resolved
282cf57 to
df6ee7b
Compare
There was a problem hiding this comment.
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)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (1)
9-9: UseproxyHandler.nameinstead of hardcoded string in describe block.As per coding guidelines, the root describe suite description should use
<Subject>.nameinstead of a hardcoded string to enable automated refactoring tools to find all references.🔎 Proposed fix
-describe("proxy API handler", () => { +describe(proxyHandler.name, () => {Based on coding guidelines: "Use
<Subject>.namein the root describe suite description instead of hardcoded class/service name strings".
♻️ Duplicate comments (3)
apps/deploy-web/src/pages/api/bitbucket/authenticate.ts (1)
14-15: Non-null assertion still risks runtime failure.The non-null assertion on
NEXT_PUBLIC_BITBUCKET_CLIENT_IDremains from the previous review. If this environment variable is missing, the code will fail at runtime whenBitbucketAuthattempts to use it.Add runtime validation to ensure these values are defined before use.
🔎 Proposed validation
async handler({ body, res, services }) { const { NEXT_PUBLIC_BITBUCKET_CLIENT_ID, BITBUCKET_CLIENT_SECRET } = services.privateConfig; + + if (!NEXT_PUBLIC_BITBUCKET_CLIENT_ID || !BITBUCKET_CLIENT_SECRET) { + return res.status(500).json({ error: "Bitbucket OAuth is not configured" }); + } - const bitbucketAuth = new BitbucketAuth(NEXT_PUBLIC_BITBUCKET_CLIENT_ID!, BITBUCKET_CLIENT_SECRET, services.externalApiHttpClient); + const bitbucketAuth = new BitbucketAuth(NEXT_PUBLIC_BITBUCKET_CLIENT_ID, BITBUCKET_CLIENT_SECRET, services.externalApiHttpClient);apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
170-170: Remove leftover debug text.Line 170 contains "test me here?" which is debug text that should be removed before merging.
🔎 Proposed fix
- test me here?apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
65-90: Stale closure in error handler.Line 82 captures
statusfrom the closure, which may be stale when the error event fires. Thestatusstate variable could have changed between whenrenderAndWaitResponseis called and when the error event is dispatched.Consider removing
statusfrom the rejection payload since it's captured at render time, not at error time:🔎 Proposed fix
eventBus.current.addEventListener( "error", event => { const details = (event as CustomEvent<{ reason: string; error?: string }>).detail; - reject({ status, ...details }); + reject(details); }, { once: true } );
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (38)
apps/deploy-web/env/.env.sampleapps/deploy-web/playwright.config.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsxapps/deploy-web/src/components/auth/SignInForm/SignInForm.tsxapps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.tsxapps/deploy-web/src/config/env-config.schema.tsapps/deploy-web/src/hooks/useInjectedConfig.spec.tsapps/deploy-web/src/hooks/useInjectedConfig.tsapps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/middleware/verify-captcha/verify-captcha.spec.tsapps/deploy-web/src/middleware/verify-captcha/verify-captcha.tsapps/deploy-web/src/pages/_app.tsxapps/deploy-web/src/pages/api/auth/[...auth0].tsapps/deploy-web/src/pages/api/auth/password-login.tsapps/deploy-web/src/pages/api/auth/password-signup.tsapps/deploy-web/src/pages/api/auth/send-password-reset-email.tsapps/deploy-web/src/pages/api/auth/signup.tsapps/deploy-web/src/pages/api/bitbucket/authenticate.tsapps/deploy-web/src/pages/api/bitbucket/refresh.tsapps/deploy-web/src/pages/api/github/authenticate.tsapps/deploy-web/src/pages/api/gitlab/authenticate.tsapps/deploy-web/src/pages/api/gitlab/refresh.tsapps/deploy-web/src/pages/api/proxy/[...path].tsapps/deploy-web/src/pages/profile/[username]/index.tsxapps/deploy-web/src/pages/template/[id]/index.tsxapps/deploy-web/src/services/app-di-container/server-di-container.service.tsapps/deploy-web/src/services/auth/auth/auth.service.tsapps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.spec.tsapps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.tsapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.tsapps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/tests/ui/fixture/test-env.config.ts
💤 Files with no reviewable changes (6)
- apps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.ts
- apps/deploy-web/src/hooks/useInjectedConfig.ts
- apps/deploy-web/src/services/decodeInjectedConfig/decodeInjectedConfig.spec.ts
- apps/deploy-web/src/hooks/useInjectedConfig.spec.ts
- apps/deploy-web/src/pages/_app.tsx
- apps/deploy-web/tests/ui/fixture/test-env.config.ts
🚧 Files skipped from review as they are similar to previous changes (15)
- apps/deploy-web/src/pages/api/gitlab/authenticate.ts
- apps/deploy-web/src/pages/api/auth/[...auth0].ts
- apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts
- apps/deploy-web/src/pages/api/bitbucket/refresh.ts
- apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx
- apps/deploy-web/src/components/billing-usage/TrendIndicator/TrendIndicator.spec.tsx
- apps/deploy-web/src/pages/api/auth/signup.ts
- apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.spec.ts
- apps/deploy-web/src/pages/api/gitlab/refresh.ts
- apps/deploy-web/src/config/env-config.schema.ts
- apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts
- apps/deploy-web/src/pages/template/[id]/index.tsx
- apps/deploy-web/playwright.config.ts
- apps/deploy-web/src/pages/api/github/authenticate.ts
- apps/deploy-web/src/pages/api/auth/password-login.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{ts,tsx,js}: Never use typeanyor cast to typeany. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.
Files:
apps/deploy-web/src/pages/api/proxy/[...path].tsapps/deploy-web/src/pages/api/auth/password-signup.tsapps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.tsapps/deploy-web/src/middleware/verify-captcha/verify-captcha.spec.tsapps/deploy-web/src/services/app-di-container/server-di-container.service.tsapps/deploy-web/src/pages/api/bitbucket/authenticate.tsapps/deploy-web/src/services/auth/auth/auth.service.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsxapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.tsapps/deploy-web/src/pages/api/auth/send-password-reset-email.tsapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/components/turnstile/Turnstile.tsxapps/deploy-web/src/components/turnstile/Turnstile.spec.tsxapps/deploy-web/src/pages/profile/[username]/index.tsx
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under testUse
setupfunction instead ofbeforeEachin test files. Thesetupfunction must be at the bottom of the rootdescribeblock, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
**/*.spec.{ts,tsx}: Use<Subject>.namein the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Use either a method name or a condition starting with 'when' for nested suite descriptions in tests
Use present simple, 3rd person singular for test descriptions without prepending 'should'
Files:
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.spec.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
{apps/deploy-web,apps/provider-console}/**/*.spec.tsx
📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)
Use
queryBymethods instead ofgetBymethods in test expectations
Files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
🧠 Learnings (15)
📚 Learning: 2025-11-25T17:45:44.790Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-11-25T17:45:44.790Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test
Applied to files:
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.spec.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
📚 Learning: 2025-11-25T17:45:52.965Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-11-25T17:45:52.965Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files. The `setup` function must be at the bottom of the root `describe` block, should create an object under test and return it, accept a single parameter with inline type definition, avoid shared state, and not have a specified return type.
Applied to files:
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.spec.tsapps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/tests/ui/fixture/base-test.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
📚 Learning: 2025-09-04T04:27:40.858Z
Learnt from: stalniy
Repo: akash-network/console PR: 1868
File: apps/api/src/billing/services/managed-signer/managed-signer.service.ts:98-107
Timestamp: 2025-09-04T04:27:40.858Z
Learning: In the Akash protocol, when processing MsgCreateLease messages, the bidId.dseq field is always required and guaranteed to be present at runtime, even though TypeScript types may suggest it could be undefined. The non-null assertion operator (!) is appropriate to use in this context.
Applied to files:
apps/deploy-web/src/pages/api/bitbucket/authenticate.ts
📚 Learning: 2025-12-26T20:06:01.746Z
Learnt from: stalniy
Repo: akash-network/console PR: 2421
File: apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx:90-96
Timestamp: 2025-12-26T20:06:01.746Z
Learning: In the SignInForm component (apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx), the "Forgot password?" link intentionally uses tabIndex={-1} to keep it out of the keyboard tab order between email and password fields, ensuring a smooth tab flow through the form inputs without interruption.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
📚 Learning: 2025-07-11T10:46:43.711Z
Learnt from: stalniy
Repo: akash-network/console PR: 1660
File: apps/deploy-web/src/components/alerts/DeploymentAlertsContainer/DeploymentAlertsContainer.spec.tsx:54-56
Timestamp: 2025-07-11T10:46:43.711Z
Learning: In apps/{deploy-web,provider-console}/**/*.spec.tsx files: Use `getBy` methods instead of `queryBy` methods when testing element presence with `toBeInTheDocument()` because `getBy` throws an error and shows DOM state when element is not found, providing better debugging information than `queryBy` which returns null.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsxapps/deploy-web/src/components/auth/AuthPage/AuthPage.tsxapps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-09-10T08:40:53.104Z
Learnt from: stalniy
Repo: akash-network/console PR: 1892
File: apps/deploy-web/src/components/new-deployment/BidCountdownTimer.tsx:20-31
Timestamp: 2025-09-10T08:40:53.104Z
Learning: In TanStack Query v5, the onSuccess and onError callbacks were removed from useQuery options. Instead, use useEffect with the data as a dependency to handle side effects when query data changes.
Applied to files:
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx
📚 Learning: 2025-11-19T15:15:07.283Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 2254
File: apps/api/test/functional/sign-and-broadcast-tx.spec.ts:4-4
Timestamp: 2025-11-19T15:15:07.283Z
Learning: In the Akash Network Console project, when tests use native Node.js fetch (available in Node 18+), fetch-mock should be used for HTTP mocking instead of nock, as nock does not support intercepting native fetch calls. This applies to apps/api/test/functional/sign-and-broadcast-tx.spec.ts and any other tests using native fetch.
Applied to files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/src/components/turnstile/Turnstile.spec.tsx
📚 Learning: 2025-11-25T17:45:49.180Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-11-25T17:45:49.180Z
Learning: Applies to {apps/deploy-web,apps/provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations
Applied to files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.tsapps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-11-25T17:45:58.258Z
Learnt from: CR
Repo: akash-network/console PR: 0
File: .cursor/rules/test-descriptions.mdc:0-0
Timestamp: 2025-11-25T17:45:58.258Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `<Subject>.name` in the root describe suite description instead of hardcoded class/service name strings to enable automated refactoring tools to find all references
Applied to files:
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts
📚 Learning: 2025-10-15T16:39:55.348Z
Learnt from: jzsfkzm
Repo: akash-network/console PR: 2039
File: apps/deploy-web/tests/ui/change-wallets.spec.ts:4-10
Timestamp: 2025-10-15T16:39:55.348Z
Learning: In the Akash Console E2E tests using the context-with-extension fixture, the first wallet is automatically created during fixture setup via `importWalletToLeap` in `apps/deploy-web/tests/ui/fixture/wallet-setup.ts`, so tests that call `frontPage.createWallet()` are creating a second wallet to test wallet switching functionality.
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-05-22T14:25:01.336Z
Learnt from: stalniy
Repo: akash-network/console PR: 1353
File: apps/deploy-web/src/config/browser-env.config.ts:0-0
Timestamp: 2025-05-22T14:25:01.336Z
Learning: For the `__AK_INJECTED_CONFIG__` global window property in the Akash Network Console, security is handled through cryptographic signature verification using a public key rather than property protection mechanisms like Object.defineProperty.
Applied to files:
apps/deploy-web/tests/ui/fixture/base-test.ts
📚 Learning: 2025-10-31T11:26:42.138Z
Learnt from: stalniy
Repo: akash-network/console PR: 2138
File: apps/api/src/billing/lib/batch-signing-client/batch-signing-client.service.ts:379-382
Timestamp: 2025-10-31T11:26:42.138Z
Learning: In TypeScript/JavaScript, the pattern of checking a cached value and then performing an async operation to fetch it without proper synchronization is race condition unsafe:
```typescript
private async getAddress() {
if (!this.address) {
this.address = await this.wallet.getFirstAddress();
}
return this.address;
}
```
Multiple concurrent calls can all pass the `if (!this.address)` check before any of them sets the value, leading to duplicate async operations. This should be flagged as a race condition. Proper synchronization (mutex, atomic promise caching, or guaranteed single-threaded execution) is required.
Applied to files:
apps/deploy-web/src/components/turnstile/Turnstile.tsx
📚 Learning: 2025-09-29T03:58:26.414Z
Learnt from: stalniy
Repo: akash-network/console PR: 1971
File: apps/deploy-web/src/components/home/YourAccount.tsx:234-239
Timestamp: 2025-09-29T03:58:26.414Z
Learning: In the Akash Network Console project, the UI components use CSS approach for disabling elements with aria-disabled="true" using "aria-[disabled='true']:pointer-events-none aria-[disabled='true']:opacity-50" classes, as seen in the button component. This pattern should be extended to links for consistency.
Applied to files:
apps/deploy-web/src/components/turnstile/Turnstile.tsx
📚 Learning: 2025-08-12T13:52:38.708Z
Learnt from: stalniy
Repo: akash-network/console PR: 1800
File: apps/deploy-web/next.config.js:163-165
Timestamp: 2025-08-12T13:52:38.708Z
Learning: In the Akash Console project, akashnetwork/env-loader is used at the top of next.config.js files to automatically load environment variables from env/.env files into process.env. SENTRY_ORG and SENTRY_PROJECT are stored as public configuration values in apps/deploy-web/env/.env and are loaded this way, while only SENTRY_AUTH_TOKEN is handled as a GitHub secret in workflows.
Applied to files:
apps/deploy-web/env/.env.sample
📚 Learning: 2025-08-12T13:52:38.708Z
Learnt from: stalniy
Repo: akash-network/console PR: 1800
File: apps/deploy-web/next.config.js:163-165
Timestamp: 2025-08-12T13:52:38.708Z
Learning: In the Akash Console project, SENTRY_ORG and SENTRY_PROJECT are stored as public configuration values in apps/deploy-web/env/.env file and loaded by akashnetwork/env-loader, not as GitHub secrets. Only SENTRY_AUTH_TOKEN should be handled as a secret.
Applied to files:
apps/deploy-web/env/.env.sample
🧬 Code graph analysis (13)
apps/deploy-web/src/pages/api/proxy/[...path].ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/pages/api/auth/password-signup.ts (1)
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (1)
verifyCaptcha(6-29)
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.spec.ts (3)
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (1)
verifyCaptcha(6-29)apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (1)
TurnstileVerifierService(5-57)apps/deploy-web/src/lib/nextjs/defineServerSideProps/defineServerSideProps.ts (1)
AppTypedContext(24-31)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (2)
apps/deploy-web/src/services/session/session.service.ts (1)
SessionService(10-217)apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (1)
TurnstileVerifierService(5-57)
apps/deploy-web/src/pages/api/bitbucket/authenticate.ts (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (3)
apps/deploy-web/src/components/auth/SignInForm/SignInForm.tsx (2)
SignInForm(38-123)DEPENDENCIES(27-36)apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
DEPENDENCIES(25-46)apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
TurnstileRef(26-28)
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (2)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (2)
ClientOnlyTurnstile(160-160)TurnstileRef(26-28)apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
useServices(33-35)
apps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (1)
apps/deploy-web/src/pages/api/proxy/[...path].ts (1)
config(59-64)
apps/deploy-web/src/pages/api/auth/send-password-reset-email.ts (2)
apps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.ts (1)
defineApiHandler(13-57)apps/deploy-web/src/middleware/verify-captcha/verify-captcha.ts (1)
verifyCaptcha(6-29)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (2)
apps/api/test/services/mock-config.service.ts (1)
mockConfig(10-17)apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
apps/deploy-web/src/utils/getInjectedConfig/getInjectedConfig.ts (1)
getInjectedConfig(3-5)
apps/deploy-web/src/components/turnstile/Turnstile.spec.tsx (1)
apps/deploy-web/src/components/turnstile/Turnstile.tsx (3)
COMPONENTS(20-24)TurnstileRef(26-28)Turnstile(38-158)
apps/deploy-web/src/pages/profile/[username]/index.tsx (1)
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
services(25-61)
🪛 dotenv-linter (4.0.0)
apps/deploy-web/env/.env.sample
[warning] 53-53: [UnorderedKey] The E2E_TESTING_CLIENT_TOKEN key should go before the NEXT_PUBLIC_TURNSTILE_ENABLED key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (24)
apps/deploy-web/src/lib/nextjs/pages/api/proxy/path.spec.ts (1)
33-33: LGTM! Property name mismatch resolved and type safety improved.The changes correctly address the previous review feedback by:
- Renaming the mock type to
services.privateConfig(line 33)- Updating the property name to
privateConfig(line 77) to match the production structure inserver-di-container.service.ts- Improving type safety by using
satisfiesinstead of type assertion (line 79), which provides better compile-time checkingAlso applies to: 77-77, 79-79
apps/deploy-web/src/pages/profile/[username]/index.tsx (1)
26-29: LGTM! Config migration correctly applied and consistent across codebase.The migration from
services.configtoservices.privateConfigon line 28 is correct and properly separates server-side configuration from client-exposed config. This pattern has been consistently applied across all server-side handlers in the codebase—no remaining references to the old pattern exist, and type safety is maintained throughout with properGetServerSidePropsResult<Props>typing.apps/deploy-web/tests/ui/fixture/base-test.ts (1)
13-22: LGTM! Config injection simplified correctly.The changes successfully remove the complex signing flow in favor of a straightforward frozen config injection. The dummy Turnstile site key is correctly sourced from Cloudflare's testing documentation, and past review concerns (guard removal and typo fix) have been addressed.
apps/deploy-web/src/lib/nextjs/defineApiHandler/defineApiHandler.ts (2)
18-20: LGTM! Method validation correctly positioned before request processing.The method guard correctly returns a 405 status before session retrieval and schema validation, which is the appropriate order for HTTP method enforcement.
64-64: LGTM! HTTP method constraint added to API handler options.The optional method field provides a clean way to enforce HTTP method constraints at the handler definition level, preventing method-based routing errors.
apps/deploy-web/src/pages/api/proxy/[...path].ts (1)
41-41: LGTM! Config source correctly migrated to privateConfig.The change from
services.configtoservices.privateConfigis consistent with the broader configuration migration pattern across the codebase, aligning with the server DI container updates.apps/deploy-web/env/.env.sample (1)
49-53: LGTM! Turnstile environment variables correctly configured.The new environment variables for Turnstile integration are properly documented with dummy test keys from Cloudflare's official documentation. The grouping of related variables together is more intuitive than strict alphabetical ordering.
apps/deploy-web/src/components/auth/AuthPage/AuthPage.spec.tsx (4)
115-118: LGTM! Captcha token correctly verified in sign-in flow.The assertion now includes
captchaToken: "test-captcha-token"from the mocked Turnstile component, ensuring the authentication payload includes the captcha token.
176-179: LGTM! Captcha token correctly verified in sign-up flow.The assertion includes the captcha token from the mocked Turnstile, verifying the complete authentication payload structure.
216-256: LGTM! Comprehensive forgot password flow coverage.The new test suite properly verifies:
- Rendering transition from SignInForm to ForgotPasswordForm
- Router state updates via
replace- Captcha token inclusion in password reset email payload
296-303: LGTM! TurnstileMock correctly implements test interface.The mock properly exposes the
renderAndWaitResponsemethod through the ref, returning a test captcha token that flows through to authentication assertions. The direct ref mutation (line 298) is a pragmatic approach for test mocking.apps/deploy-web/src/services/auth/auth/auth.service.ts (3)
32-37: LGTM! Captcha token correctly added to login flow.The
loginmethod signature and payload correctly include thecaptchaTokenparameter, aligning with the server-side captcha verification in the password-login API endpoint.
40-46: LGTM! Captcha token correctly added to signup flow.The
signupmethod signature and payload correctly include thecaptchaTokenparameter, aligning with the server-side captcha verification in the password-signup API endpoint.
49-54: LGTM! Captcha token correctly added to password reset flow.The
sendPasswordResetEmailmethod signature and payload correctly include thecaptchaTokenparameter, aligning with the server-side captcha verification in the send-password-reset-email API endpoint.apps/deploy-web/src/pages/api/auth/password-signup.ts (3)
14-14: LGTM! HTTP method constraint correctly enforces POST.The explicit
method: "POST"declaration leverages the new API handler method validation, ensuring only POST requests are accepted for signup operations.
36-36: LGTM! Captcha token correctly added to request schema.The
captchaToken: z.string()field ensures the captcha token is present and validated before handler execution.
39-43: LGTM! Captcha verification correctly positioned before signup logic.The verification happens immediately after extracting the context, short-circuiting the signup flow with a 400 response if verification fails. This prevents unnecessary processing and protects the signup endpoint from abuse.
apps/deploy-web/src/pages/api/auth/send-password-reset-email.ts (1)
1-17: LGTM! Clean integration of captcha verification.The API handler properly enforces POST method, validates the request schema including captchaToken, and integrates captcha verification middleware.
apps/deploy-web/src/middleware/verify-captcha/verify-captcha.spec.ts (1)
1-186: Excellent test coverage following all coding guidelines.The test suite comprehensively covers:
- Disabled state bypass
- Success and failure scenarios
- Bypass token propagation
- Remote IP extraction precedence (cf-connecting-ip → x-real-ip → x-forwarded-for → socket)
The implementation correctly uses the
setupfunction pattern,jest-mock-extended, and proper test descriptions.Based on coding guidelines, the setup function and test structure align with project conventions.
apps/deploy-web/src/services/app-di-container/server-di-container.service.ts (1)
13-61: LGTM! Clean DI container integration.The changes properly:
- Introduce
privateConfigprovider exposing server-side environment configuration- Wire
TurnstileVerifierServicewith appropriate secrets fromprivateConfig- Migrate Auth0 and network ID configuration to use
privateConfigconsistentlyapps/deploy-web/src/services/turnstile-verifier/turnstile-verifier.service.ts (1)
33-34: Bypass logic correctly prevents undefined comparison.The current implementation properly guards against the
undefined === undefinedissue mentioned in past reviews by checkingbypassSecretKeyVerificationTokenis truthy before performing the equality check. This ensures the bypass secret is only used when explicitly configured.apps/deploy-web/src/components/turnstile/Turnstile.spec.tsx (1)
1-187: Well-structured tests following coding guidelines.The test suite properly exercises the new
TurnstileRefAPI includingrenderAndWaitResponseflow. Tests correctly use thesetupfunction pattern,jest-mock-extended, and proper test descriptions.Based on coding guidelines, the implementation aligns with project test conventions.
apps/deploy-web/src/components/auth/AuthPage/AuthPage.tsx (1)
69-79: Clean captcha integration with proper error handling.The implementation correctly guards against missing turnstileRef, awaits the captcha token via
renderAndWaitResponse, and passes it to the authentication services.apps/deploy-web/src/components/turnstile/Turnstile.tsx (1)
144-149: Accessibility improved with aria-labels.The action buttons now include proper
aria-labelattributes ("Reload captcha" and "Dismiss captcha"), addressing the accessibility concern from past reviews.
| const verification = await verifyCaptcha(body.captchaToken, ctx); | ||
| if (verification.err) return res.status(400).json(verification.val); | ||
|
|
||
| const result = await services.sessionService.sendPasswordResetEmail({ email: req.body.email }); |
There was a problem hiding this comment.
Use validated body.email instead of req.body.email.
Line 22 accesses req.body.email, but body was already destructured from the validated context at line 16. This is inconsistent with line 19's use of body.captchaToken and bypasses the Zod validation.
🔎 Proposed fix
- const result = await services.sessionService.sendPasswordResetEmail({ email: req.body.email });
+ const result = await services.sessionService.sendPasswordResetEmail({ email: body.email });📝 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.
| const result = await services.sessionService.sendPasswordResetEmail({ email: req.body.email }); | |
| const result = await services.sessionService.sendPasswordResetEmail({ email: body.email }); |
🤖 Prompt for AI Agents
In apps/deploy-web/src/pages/api/auth/send-password-reset-email.ts around line
22, the code calls services.sessionService.sendPasswordResetEmail with
req.body.email which bypasses the previously validated and destructured body
variable; replace req.body.email with the validated body.email so the call uses
the Zod-validated input (and update any other occurrences to consistently use
body rather than req.body).
Why
ref #2400
What
Screen.Recording.2025-12-26.at.17.20.37.mov
Summary by CodeRabbit
New Features
Bug Fixes / Improvements
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.