From 9a78c71efa292455b3080ca9fd21e24474f7a61d Mon Sep 17 00:00:00 2001 From: rohitneharabrowserstack Date: Thu, 27 Aug 2026 14:44:51 +0530 Subject: [PATCH] fix(security): RQ-3893 remove the AppSumo redemption flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AppSumo is being retired, so the escalation path this ticket describes is removed rather than guarded. The redemption screen was the only client-side reader and writer of the `appSumoCodes` collection — it validated a typed code with `getDoc` and marked it `redeemed` in a batch write — which is the sole reason the Firestore rules had to grant every authenticated user read+update on that collection. Removed, all of it reachable only from the redemption screen: - components/landing/Appsumo/ (the modal and its workspace dropdown) - the /appsumo route and PATHS.APPSUMO - the entry in onboarding's EXCLUDED_PATHS - the "Signup to redeem your AppSumo code" variant of the signup header, plus the now-orphaned PATHS / useLocation imports it was the last consumer of - trackAppsumoCodeRedeemed and its APPSUMO_CODE_REDEEMED event name Deliberately kept: everything that serves customers who already hold the deal. An AppSumo plan is a persisted value on the team document (`plan: 'basic_appsumo_v0'`), not something derived from `appsumo.codes` at read time, so entitlement display and gating — PremiumPlanBadge, PricingUtils' "AppSumo" label, UserPlanDetails, ActiveLicenseInfo, PlanType.APPSUMO — are untouched. Removing those would revoke live lifetime plans, which is a separate decision with a migration attached. Co-Authored-By: Claude Opus 5 (1M context) --- .../authentication/AuthForm/index.js | 8 +- .../AppSumoWorkspaceDropdown.tsx | 142 ------- .../AppSumoWorkspaceDropdown/index.scss | 33 -- .../components/landing/Appsumo/Appsumo.tsx | 348 ------------------ app/src/components/landing/Appsumo/index.scss | 31 -- app/src/config/constants/sub/paths.js | 5 - app/src/features/onboarding/utils.ts | 1 - .../analytics/events/misc/business/index.js | 5 - .../analytics/events/misc/constants.js | 1 - app/src/routes/miscRoutes.tsx | 5 - 10 files changed, 2 insertions(+), 577 deletions(-) delete mode 100644 app/src/components/landing/Appsumo/AppSumoWorkspaceDropdown/AppSumoWorkspaceDropdown.tsx delete mode 100644 app/src/components/landing/Appsumo/AppSumoWorkspaceDropdown/index.scss delete mode 100644 app/src/components/landing/Appsumo/Appsumo.tsx delete mode 100644 app/src/components/landing/Appsumo/index.scss diff --git a/app/src/components/authentication/AuthForm/index.js b/app/src/components/authentication/AuthForm/index.js index 85ea1f8ae0..20d2e99024 100644 --- a/app/src/components/authentication/AuthForm/index.js +++ b/app/src/components/authentication/AuthForm/index.js @@ -1,6 +1,6 @@ import React, { useState, useEffect, useMemo, useCallback } from "react"; import { useSelector } from "react-redux"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router-dom"; import { RQButton, RQInput } from "lib/design-system/components"; import { toast } from "utils/Toast"; import { Typography, Row, Col } from "antd"; @@ -17,7 +17,6 @@ import { getAuthErrorMessage, AuthTypes } from "../utils"; //CONSTANTS import { CONSTANTS as GLOBAL_CONSTANTS } from "@requestly/requestly-core"; import APP_CONSTANTS from "../../../config/constants"; -import PATHS from "config/constants/sub/paths"; //ACTIONS import { @@ -54,7 +53,6 @@ const AuthForm = ({ }) => { const dispatch = useDispatch(); const navigate = useNavigate(); - const location = useLocation(); //LOAD PROPS const callbackFromProps = callbacks || {}; const { onSignInSuccess, onRequestPasswordResetSuccess } = callbackFromProps; @@ -440,9 +438,7 @@ const AuthForm = ({ - {location.pathname === PATHS.APPSUMO.RELATIVE - ? "Signup to redeem your AppSumo code" - : "Create your Requestly account"} + Create your Requestly account diff --git a/app/src/components/landing/Appsumo/AppSumoWorkspaceDropdown/AppSumoWorkspaceDropdown.tsx b/app/src/components/landing/Appsumo/AppSumoWorkspaceDropdown/AppSumoWorkspaceDropdown.tsx deleted file mode 100644 index 4877b852af..0000000000 --- a/app/src/components/landing/Appsumo/AppSumoWorkspaceDropdown/AppSumoWorkspaceDropdown.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import React, { useCallback, useEffect, useMemo } from "react"; -import { DownOutlined, LockOutlined } from "@ant-design/icons"; -import { Avatar, Dropdown, Typography } from "antd"; -import { RQButton } from "lib/design-system/components"; -import { useSelector } from "react-redux"; -import { getUserAuthDetails } from "store/slices/global/user/selectors"; -import APP_CONSTANTS from "config/constants"; -import "./index.scss"; -import { getActiveWorkspaceId, getAllWorkspaces } from "store/slices/workspaces/selectors"; -import { WorkspaceType } from "features/workspaces/types"; -import WorkspaceAvatar from "features/workspaces/components/WorkspaceAvatar"; -import { isPersonalWorkspace } from "features/workspaces/utils"; - -const getWorkspaceIcon = (workspaceName: string) => { - if (workspaceName === APP_CONSTANTS.TEAM_WORKSPACES.NAMES.PRIVATE_WORKSPACE) return ; - return workspaceName ? workspaceName[0].toUpperCase() : "?"; -}; - -const AppSumoWorkspaceDropdown: React.FC<{ - isAppSumo?: boolean; - workspaceToUpgrade: { name: string; id: string; accessCount: number }; - setWorkspaceToUpgrade: (workspaceDetails: any) => void; - className?: string; - disabled?: boolean; -}> = ({ isAppSumo = false, workspaceToUpgrade, setWorkspaceToUpgrade, className, disabled = false }) => { - const user = useSelector(getUserAuthDetails); - const availableWorkspaces = useSelector(getAllWorkspaces); - const activeWorkspaceId = useSelector(getActiveWorkspaceId); - - const filteredAvailableTeams = useMemo(() => { - return ( - availableWorkspaces?.filter( - (team: any) => - !team?.archived && - user?.details?.profile?.uid && - team.members?.[user?.details?.profile?.uid]?.role === "admin" - ) ?? [] - ); - }, [availableWorkspaces, user?.details?.profile?.uid]); - - const populateWorkspaceDetails = useCallback( - (workspaceId: string) => { - return filteredAvailableTeams.find((team: any) => team.id === workspaceId); - }, - [filteredAvailableTeams] - ); - - useEffect(() => { - if (activeWorkspaceId) { - setWorkspaceToUpgrade(populateWorkspaceDetails(activeWorkspaceId)); - } - }, [activeWorkspaceId, populateWorkspaceDetails, setWorkspaceToUpgrade]); - - const workspaceMenuItems = { - items: [ - { - key: "private_workspace", - label: APP_CONSTANTS.TEAM_WORKSPACES.NAMES.PRIVATE_WORKSPACE, - icon: ( - - ), - }, - ...filteredAvailableTeams.map((team: any) => ({ - label: team.name, - key: team.id, - icon: , - })), - ].filter((items) => (isAppSumo ? items.key !== "private_workspace" : true)), - onClick: ({ key: teamId }: { key: string }) => { - if (teamId === "private_workspace") { - return setWorkspaceToUpgrade({ - name: APP_CONSTANTS.TEAM_WORKSPACES.NAMES.PRIVATE_WORKSPACE, - id: "private_workspace", - accessCount: 1, - }); - } else if (teamId === APP_CONSTANTS.TEAM_WORKSPACES.NEW_WORKSPACE.id) { - // temporary new workspace for appsumo - return setWorkspaceToUpgrade({ - ...APP_CONSTANTS.TEAM_WORKSPACES.NEW_WORKSPACE, - }); - } - - setWorkspaceToUpgrade(populateWorkspaceDetails(teamId)); - }, - }; - - if (isAppSumo) { - workspaceMenuItems.items.unshift({ - key: APP_CONSTANTS.TEAM_WORKSPACES.NEW_WORKSPACE.id, - label: APP_CONSTANTS.TEAM_WORKSPACES.NEW_WORKSPACE.name, - icon: ( - - ), - }); - } - - return user.loggedIn ? ( -
-
- Select workspace to upgrade - - -
- - {workspaceToUpgrade?.name} - -
-
-
-
- {(isAppSumo || workspaceToUpgrade?.id !== "private_workspace") && ( -
- - Your workspace has {workspaceToUpgrade?.accessCount} active{" "} - {workspaceToUpgrade?.accessCount > 1 ? "members" : "member"}. - -
- )} -
- ) : null; -}; - -export default AppSumoWorkspaceDropdown; diff --git a/app/src/components/landing/Appsumo/AppSumoWorkspaceDropdown/index.scss b/app/src/components/landing/Appsumo/AppSumoWorkspaceDropdown/index.scss deleted file mode 100644 index c26279611e..0000000000 --- a/app/src/components/landing/Appsumo/AppSumoWorkspaceDropdown/index.scss +++ /dev/null @@ -1,33 +0,0 @@ -.workspace-selector-container { - display: flex; - flex-direction: column; - margin-bottom: 1rem; - width: 100%; - - .workspace-selector-dropdown-container { - margin-bottom: 4px; - - .workspace-selector-dropdown { - &.ant-dropdown-menu-root { - overflow: auto; - max-height: 15rem; - } - } - - .workspace-selector-dropdown-btn.ant-btn.rq-btn { - background-color: var(--requestly-color-surface-1); - border: none; - margin-left: 4px; - padding: 8px; - - &:hover { - border: none; - } - - .workspace-selector-dropdown-icon.anticon { - margin-left: 2px; - font-size: 0.7rem; - } - } - } -} diff --git a/app/src/components/landing/Appsumo/Appsumo.tsx b/app/src/components/landing/Appsumo/Appsumo.tsx deleted file mode 100644 index 6bee9c47d5..0000000000 --- a/app/src/components/landing/Appsumo/Appsumo.tsx +++ /dev/null @@ -1,348 +0,0 @@ -import React, { useCallback, useEffect, useMemo, useState } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { getAppMode } from "store/selectors"; -import { Row } from "antd"; -import APP_CONSTANTS from "config/constants"; -import { RQButton, RQInput, RQModal } from "lib/design-system/components"; -import { ImCross } from "@react-icons/all-files/im/ImCross"; -import { MdOutlineVerified } from "@react-icons/all-files/md/MdOutlineVerified"; -import { FiXCircle } from "@react-icons/all-files/fi/FiXCircle"; -import { useNavigate } from "react-router-dom"; -import { redirectToRoot } from "utils/RedirectionUtils"; -import AppSumoWorkspaceDropdown from "components/landing/Appsumo/AppSumoWorkspaceDropdown/AppSumoWorkspaceDropdown"; -import { doc, getDoc, getFirestore, writeBatch } from "firebase/firestore"; -import firebaseApp from "../../../firebase"; -import { toast } from "utils/Toast"; -import { isEmailValid } from "utils/FormattingHelper"; -import { useDebounce } from "hooks/useDebounce"; -import { httpsCallable, getFunctions } from "firebase/functions"; -import { trackNewTeamCreateSuccess } from "modules/analytics/events/features/teams"; -import { trackAppsumoCodeRedeemed } from "modules/analytics/events/misc/business"; -import { switchWorkspace } from "actions/TeamWorkspaceActions"; -import { globalActions } from "store/slices/global/slice"; -import "./index.scss"; -import { getAllWorkspaces } from "store/slices/workspaces/selectors"; -import { WorkspaceType } from "features/workspaces/types"; - -interface AppSumoCode { - error: string; - code: string; - verified: boolean; -} - -const DEFAULT_APPSUMO_INPUT: AppSumoCode = { - error: "", - code: "", - verified: false, -}; - -const AppSumoModal: React.FC = () => { - const navigate = useNavigate(); - const dispatch = useDispatch(); - const appMode = useSelector(getAppMode); - const availableWorkspaces = useSelector(getAllWorkspaces); - const [appsumoCodes, setAppsumoCodes] = useState([{ ...DEFAULT_APPSUMO_INPUT }]); - const [userEmail, setUserEmail] = useState(""); - const [emailValidationError, setEmailValidationError] = useState(null); - const [workspaceToUpgrade, setWorkspaceToUpgrade] = useState(APP_CONSTANTS.TEAM_WORKSPACES.NEW_WORKSPACE); - const [isLoading, setIsLoading] = useState(false); - const [isUpdatingSubscription, setIsUpdatingSubscription] = useState(false); - const [showMaxCodesExeceededError, setShowMaxCodesExeceededError] = useState(false); - - const db = getFirestore(firebaseApp); - - const addAppSumoCodeInput = () => { - if (appsumoCodes.length >= 10) { - setShowMaxCodesExeceededError(true); - return; - } - setAppsumoCodes((prev) => [...prev, { ...DEFAULT_APPSUMO_INPUT }]); - }; - - const removeAppSumoCodeInput = (index: number) => { - if (appsumoCodes.length === 1) return; - setAppsumoCodes((prev) => { - const codes = [...prev]; - codes.splice(index, 1); - return codes; - }); - }; - - const isAllCodeCheckPassed = useMemo(() => appsumoCodes.every((code) => code.verified), [appsumoCodes]); - - const updateAppSumoCode = (index: number, key: keyof AppSumoCode, value: AppSumoCode[typeof key]) => { - setAppsumoCodes((prev) => { - const codes: AppSumoCode[] = [...prev]; - if (codes[index]) { - (codes[index] as any)[key] = value; - } - return codes; - }); - }; - - const debouncedVerifyCode = useDebounce((enteredCode: string, index: number) => verifyCode(enteredCode, index)); - - const verifyCode = useCallback( - async (enteredCode: string, index: number) => { - if (enteredCode.length < 8) { - updateAppSumoCode(index, "verified", false); - return; - } - - const codeOccurence = appsumoCodes.filter((appsumoCode: AppSumoCode) => appsumoCode.code === enteredCode).length; - if (codeOccurence > 1) { - updateAppSumoCode(index, "error", "Code already used"); - updateAppSumoCode(index, "verified", false); - return; - } - - const docRef = doc(db, "appSumoCodes", enteredCode); - const docSnap = await getDoc(docRef); - - if (!docSnap.exists()) { - updateAppSumoCode(index, "error", "Invalid code"); - updateAppSumoCode(index, "verified", false); - return; - } - - if (docSnap.data()?.redeemed) { - updateAppSumoCode(index, "error", "Code already redeemed"); - updateAppSumoCode(index, "verified", false); - return; - } - updateAppSumoCode(index, "error", ""); - updateAppSumoCode(index, "verified", true); - }, - [db, appsumoCodes] - ); - - const redeemSubmittedCodes = useCallback(async () => { - const batch = writeBatch(db); - appsumoCodes.forEach((code) => { - const docRef = doc(db, "appSumoCodes", code.code); - batch.update(docRef, { redeemed: true }); - }); - await batch.commit(); - }, [db, appsumoCodes]); - - const createNewWorkspaceForAppSumo = useCallback(async () => { - setIsLoading(true); - - const newTeamName = "Team Workspace"; - const createTeam = httpsCallable(getFunctions(), "teams-createTeam"); - try { - const response: any = await createTeam({ teamName: newTeamName }); - trackNewTeamCreateSuccess(response?.data?.teamId, newTeamName, "appsumo", WorkspaceType.SHARED); - switchWorkspace( - { - teamId: response?.data?.teamId, - teamMembersCount: 1, - }, - dispatch, - { - isWorkspaceMode: false, - isSyncEnabled: true, - }, - appMode, - null, - "appsumo" - ); - - setIsLoading(false); - return response?.data?.teamId; - } catch (error) { - // do nothing - } - }, [appMode, dispatch]); - - const onSubmit = useCallback(async () => { - if (!isAllCodeCheckPassed || emailValidationError) { - toast.warn("Please fill all the fields correctly", 10); - throw new Error("Please fill all the fields correctly"); - } - setIsUpdatingSubscription(true); - - let teamId = workspaceToUpgrade.id; - if (workspaceToUpgrade.id === APP_CONSTANTS.TEAM_WORKSPACES.NEW_WORKSPACE.id) { - teamId = await createNewWorkspaceForAppSumo(); - } - - const updateTeamSubscriptionForAppSumo = httpsCallable<{}, { success: boolean; message: string; error?: string }>( - getFunctions(), - "subscription-updateTeamSubscriptionForAppSumo" - ); - - try { - await updateTeamSubscriptionForAppSumo({ - teamId: teamId, - startDate: Date.now(), - appsumoCodes: appsumoCodes.map((code) => code.code), - }) - .then((response) => { - if (!response?.data?.success && response?.data?.error === "max_limit_reached") { - setShowMaxCodesExeceededError(true); - } else { - redeemSubmittedCodes(); - trackAppsumoCodeRedeemed(appsumoCodes.length); - toast.success( - `Lifetime access to SessionBook Plus unlocked for ${ - appsumoCodes.length > 1 ? `${appsumoCodes.length} members` : "you" - }`, - 10 - ); - redirectToRoot(navigate); - } - }) - .finally(() => { - setIsUpdatingSubscription(false); - }); - } catch (error) { - console.error("from appsumo", error); - } - }, [ - createNewWorkspaceForAppSumo, - appsumoCodes, - emailValidationError, - isAllCodeCheckPassed, - redeemSubmittedCodes, - workspaceToUpgrade?.id, - navigate, - ]); - - const handleEmailValidation = (email: string) => { - if (!email) { - setEmailValidationError("Please add your Appsumo email address"); - return; - } - if (!isEmailValid(email)) { - setEmailValidationError("Please enter a valid email address"); - return; - } - setEmailValidationError(null); - }; - - const debouncedEmailValidation = useDebounce((email: string) => handleEmailValidation(email)); - - const handleUnlockDealClick = async () => { - setShowMaxCodesExeceededError(false); - try { - await onSubmit(); - } catch (error) { - // do nothing - } - }; - - useEffect(() => { - const appsumoWorkspace = availableWorkspaces?.find((team: any) => team?.appsumo); - if (appsumoWorkspace) { - setWorkspaceToUpgrade(appsumoWorkspace as any); - } - }, [availableWorkspaces]); - - useEffect(() => { - dispatch(globalActions.updateIsWorkspaceOnboardingCompleted()); - }, [dispatch]); - - return ( - - <> -
-
- smile -
-
Please enter your AppSumo code
-

Unlock lifetime deal for SessionBook Plus

- -
AppSumo email address
-
-
- { - setUserEmail(e.target.value); - debouncedEmailValidation(e.target.value); - }} - placeholder="Enter email address here" - /> -
{emailValidationError}
-
-
-
AppSumo Code(s)
- {appsumoCodes.map((appsumoCode, index) => ( -
-
- { - updateAppSumoCode(index, "code", e.target.value); - debouncedVerifyCode(e.target.value, index); - }} - suffix={ - appsumoCode.verified ? ( - - ) : appsumoCode.error ? ( - <> - {appsumoCode.error} - - - ) : null - } - placeholder="Enter code here" - /> -
- -
- { - removeAppSumoCodeInput(index); - }} - /> -
-
- ))} - - - + Add more codes - - {showMaxCodesExeceededError && ( -
- { - "Maximum 10 AppSumo codes can be applied. Please connect with support for further help at contact@requestly.io" - } -
- )} -
- - - Unlock Deal - - - -
- ); -}; - -export default AppSumoModal; diff --git a/app/src/components/landing/Appsumo/index.scss b/app/src/components/landing/Appsumo/index.scss deleted file mode 100644 index 1e1ddb4bc1..0000000000 --- a/app/src/components/landing/Appsumo/index.scss +++ /dev/null @@ -1,31 +0,0 @@ -.rq-modal-content.appsumo-modal { - overflow: auto; - max-height: 550px; - - .appsumo-code-input-container { - display: flex; - flex-direction: column; - width: 100%; - margin-top: 4px; - - .appsumo-code-error { - text-align: right; - padding: 2px 0; - } - - .ant-input-suffix { - color: var(--requestly-color-success); - } - } - - .remove-icon { - margin: auto 6px; - height: 14px; - width: 14px; - } - - .appsumo-add-btn { - font-size: var(--requestly-font-size-sm, 13px); - padding: 0; - } -} diff --git a/app/src/config/constants/sub/paths.js b/app/src/config/constants/sub/paths.js index ebe813aa13..892036500a 100644 --- a/app/src/config/constants/sub/paths.js +++ b/app/src/config/constants/sub/paths.js @@ -47,11 +47,6 @@ PATHS.HOME = {}; PATHS.HOME.RELATIVE = "/home"; PATHS.HOME.ABSOLUTE = joinPaths(PATHS.DASHBOARD, PATHS.HOME.RELATIVE); -//Appsumo -PATHS.APPSUMO = {}; -PATHS.APPSUMO.RELATIVE = "/appsumo"; -PATHS.APPSUMO.ABSOLUTE = joinPaths(PATHS.DASHBOARD, PATHS.APPSUMO.RELATIVE); - // Selenium-importer PATHS.SELENIUM_IMPORTER = {}; PATHS.SELENIUM_IMPORTER.RELATIVE = "/selenium-importer"; diff --git a/app/src/features/onboarding/utils.ts b/app/src/features/onboarding/utils.ts index 5de73a25db..a07c2ce38e 100644 --- a/app/src/features/onboarding/utils.ts +++ b/app/src/features/onboarding/utils.ts @@ -11,7 +11,6 @@ const EXCLUDED_PATHS = [ PATHS.AUTH.EMAIL_ACTION.RELATIVE, PATHS.AUTH.EMAIL_LINK_SIGNIN.RELATIVE, PATHS.SESSIONS.SAVED.RELATIVE, - PATHS.APPSUMO.RELATIVE, PATHS.PRICING.RELATIVE, PATHS.AUTH.START.RELATIVE, PATHS.AUTH.LOGIN.RELATIVE, diff --git a/app/src/modules/analytics/events/misc/business/index.js b/app/src/modules/analytics/events/misc/business/index.js index 5b4fea9ad4..dcb95d8079 100644 --- a/app/src/modules/analytics/events/misc/business/index.js +++ b/app/src/modules/analytics/events/misc/business/index.js @@ -18,11 +18,6 @@ export const trackViewGithubClicked = () => { trackEvent(BUSINESS.VIEW_GITHUB_CLICKED); }; -export const trackAppsumoCodeRedeemed = (number_of_codes) => { - const params = { number_of_codes }; - trackEvent(BUSINESS.APPSUMO_CODE_REDEEMED, params); -}; - export const trackPricingPlanCTAClicked = ({ current_plan, selected_plan, action, quantity }, source) => { const params = { current_plan, selected_plan, action, source, quantity }; trackEvent(BUSINESS.PRICING_PLAN_CTA_CLICKED, params); diff --git a/app/src/modules/analytics/events/misc/constants.js b/app/src/modules/analytics/events/misc/constants.js index a333a1cccd..d2f583e0a5 100644 --- a/app/src/modules/analytics/events/misc/constants.js +++ b/app/src/modules/analytics/events/misc/constants.js @@ -48,7 +48,6 @@ export const BUSINESS = { TRIAL_MODE_EXPIRED_UPGRADE_BUTTON_CLICKED: "trial_mode_expired_upgrade_button_clicked", UPGRADE_CLICKED: "upgrade_clicked", VIEW_GITHUB_CLICKED: "view_github_clicked", - APPSUMO_CODE_REDEEMED: "appsumo_code_redeemed", PRICING_PLAN_CTA_CLICKED: "pricing_plan_cta_clicked", PRICING_PLAN_CANCELLATION_REQUESTED: "pricing_plan_cancellation_requested", PRICING_PLAN_CANCELLED: "pricing_plan_cancelled", diff --git a/app/src/routes/miscRoutes.tsx b/app/src/routes/miscRoutes.tsx index 2d062cd9b5..e87f26869d 100644 --- a/app/src/routes/miscRoutes.tsx +++ b/app/src/routes/miscRoutes.tsx @@ -8,7 +8,6 @@ import Page403 from "views/misc/ServerResponses/403"; import Page404 from "views/misc/ServerResponses/404"; import AcceptTeamInvite from "components/user/Teams/AcceptTeamInvite"; import ProtectedRoute from "components/authentication/ProtectedRoute"; -import AppSumoModal from "components/landing/Appsumo/Appsumo"; import { Home } from "components/Home"; import { PricingIndexPage } from "features/pricing/components/PricingPage"; import { ImportFromCharlesWrapperView } from "features/rules/screens/rulesList/components/RulesList/components"; @@ -85,10 +84,6 @@ export const miscRoutes: RouteObject[] = [ path: PATHS.HOME.RELATIVE, element: , }, - { - path: PATHS.APPSUMO.RELATIVE, - element: , - }, { path: PATHS.SELENIUM_IMPORTER.RELATIVE, element: ,