Skip to content

fix: all npm vulnerabilities#89

Merged
waltergalvao merged 7 commits intomainfrom
fix/2026-02-npm-vulnerabilities
Feb 22, 2026
Merged

fix: all npm vulnerabilities#89
waltergalvao merged 7 commits intomainfrom
fix/2026-02-npm-vulnerabilities

Conversation

@waltergalvao
Copy link
Copy Markdown
Contributor

@waltergalvao waltergalvao commented Feb 22, 2026

Greptile Summary

This PR addresses npm security vulnerabilities by upgrading multiple dependencies to their latest versions, including major version updates for Express (v4→v5), React Router (v6→v7), Vite (v6→v7), and numerous other packages.

Key Changes:

  • Migrated from react-router-dom v6 to react-router v7 across all web app components
  • Updated Express from v4 to v5 in the API
  • Upgraded build tools: Vite v7, Sentry plugin v4
  • Updated email library (Resend v3→v6) with corresponding type changes
  • Added npm overrides for ioredis, minimatch, and ajv to resolve transitive vulnerabilities
  • Bumped minimum Node.js version to 22.12.0
  • Removed vite-plugin-eslint and made devcert an optional global dependency

Issues Found:

  • TypeScript error in sync-batch service: id field added to email template object but not defined in BuildEmailTemplate interface and not used by worker

Confidence Score: 4/5

  • Safe to merge after fixing the TypeScript error in sync-batch service
  • The PR systematically addresses npm vulnerabilities with comprehensive dependency updates. The react-router v7 migration is correctly implemented across all files, API type updates align with new library versions, and breaking changes are properly handled. However, one TypeScript error exists where an id field is added to an email template object but isn't defined in the interface or used by the worker.
  • Pay close attention to apps/api/src/app/sync-batch/services/sync-batch.service.ts - contains TypeScript error that will cause compilation failure

Important Files Changed

Filename Overview
package.json Updated rimraf to v6, added npm overrides for ioredis/minimatch/ajv, bumped Node requirement to 22.12.0, removed devcert dependency
apps/web/package.json Replaced react-router-dom with react-router v7, upgraded Sentry plugin to v4, upgraded Vite to v7, removed vite-plugin-eslint, added utility-types
apps/api/package.json Major updates: express v5, bcrypt v6, bullmq v5.42, resend v6, ioredis v5.9.3, graphql-codegen v6, pino-pretty v13
apps/web/src/root.tsx Updated RouterProvider import from react-router-dom to react-router/dom for v7 compatibility
apps/api/src/lib/email.ts Updated type aliases to use explicit Resend v6 types (CreateEmailOptions, CreateEmailRequestOptions)
apps/api/src/app/sync-batch/services/sync-batch.service.ts Added id field to email template object, but field not defined in BuildEmailTemplate interface
certs/devcert.js Added try-catch for devcert import with helpful error message for missing global install

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Dependency Updates] --> B[Frontend: React Router v6→v7]
    A --> C[Backend: Express v4→v5]
    A --> D[Build Tools: Vite v6→v7]
    A --> E[Email: Resend v3→v6]
    
    B --> B1[Change imports from<br/>react-router-dom to react-router]
    B --> B2[Update RouterProvider import<br/>from react-router/dom]
    B --> B3[Update all hooks & components<br/>useNavigate, useLocation, Link, etc.]
    
    C --> C1[Update jsonwebtoken types<br/>with SignOptions]
    C --> C2[Add explicit null return<br/>for Stripe mutation]
    
    D --> D1[Remove vite-plugin-eslint]
    D --> D2[Update Sentry plugin to v4]
    
    E --> E1[Update type aliases to<br/>CreateEmailOptions]
    E --> E2[Make renderEmailTemplate async]
    E --> E3[Add await in email worker]
    
    style A fill:#e1f5ff
    style B fill:#fff4e1
    style C fill:#ffe1e1
    style D fill:#e1ffe1
    style E fill:#f4e1ff
Loading

Last reviewed commit: ca9d0e9

@sweetr-dev sweetr-dev Bot added the small Small PR - Quick and easy to review label Feb 22, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 22, 2026

Walkthrough

Monorepo-wide updates: dependency bumps and overrides, react-router → react-router-dom import replacements to react-router, async conversion of email template rendering (and callers/types), small API fixes (JWT typing, Stripe null return, json parse cast), sync email template id added, and regenerated GraphQL types with stricter resolver signatures and expanded frontend typings.

Changes

Cohort / File(s) Summary
Top-level & API manifests
package.json, apps/api/package.json
Bumped rimraf, added top-level overrides, increased Node engine, removed devcert; upgraded several API runtime deps (bcrypt, bullmq, express, ioredis, resend) and dev tooling (GraphQL codegen, added vitest).
Web manifest & Vite
apps/web/package.json, apps/web/vite.config.ts
Swapped react-router-domreact-router dependency, added utility-types, bumped vite and @sentry/vite-plugin, removed vite-plugin-eslint import/usage in Vite config.
Email templates & callers
packages/email-templates/src/index.ts, packages/email-templates/package.json, apps/api/src/app/email/workers/send-email.worker.ts, apps/api/src/lib/email.ts, apps/api/src/app/email/services/email-template.service.ts, apps/api/src/app/sync-batch/services/sync-batch.service.ts
Made renderEmailTemplate async and awaited calls; adjusted email public types to CreateEmailOptions/CreateEmailRequestOptions; added id: "initial-sync-complete" to enqueued sync email template; bumped react-email libs.
GraphQL generated types (API & frontend)
packages/graphql-types/api.ts, packages/graphql-types/frontend/gql.ts, packages/graphql-types/frontend/fragment-masking.ts, packages/graphql-types/frontend/graphql.ts
Regenerated types: tightened resolver generic defaults to Record<PropertyKey, never>, remodeled Resolvers/ResolversParentTypes with Omit/DeepPartial patterns, removed many __isTypeOf entries, added Documents mapping, expanded useFragment overloads, and changed InputMaybe to allow undefined.
Routing import updates (web app files)
apps/web/src/... (many files, e.g., apps/web/src/app/**, apps/web/src/components/**, apps/web/src/providers/**, apps/web/src/routes.tsx, apps/web/src/root.tsx)*
Replaced numerous imports from react-router-dom with react-router or react-router/dom for hooks/components (Link, Outlet, useNavigate, useParams, useSearchParams, useLocation, RouterProvider, createBrowserRouter, redirect).
Auth, Stripe, Prisma small adjustments
apps/api/src/app/auth/services/auth.service.ts, apps/api/src/app/billing/resolvers/mutations/login-to-stripe.mutation.ts, apps/api/src/prisma.ts
Imported SignOptions and inlined JWT expiresIn option typing, changed Stripe resolver to return `session?.url
Dev tooling: cert generation script
certs/devcert.js
Guarded devcert require with try/catch and added clearer error/exit messaging when unavailable.

*Many individual web files updated; see diff for full list of modified app/component/provider pages.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

huge

Suggested reviewers

  • sweetrdev
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: all npm vulnerabilities' directly aligns with the main objective of the PR, which addresses npm security vulnerabilities by upgrading multiple dependencies.
Description check ✅ Passed The pull request description clearly relates to the changeset, detailing npm security vulnerability fixes through dependency upgrades with specific version changes and their impacts.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/2026-02-npm-vulnerabilities

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

❤️ Share

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

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

12 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread apps/api/src/app/sync-batch/services/sync-batch.service.ts
Comment thread apps/api/src/app/auth/services/auth.service.ts
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

2 issues found across 12 files

Prompt for AI agents (all issues)

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


<file name="apps/web/package.json">

<violation number="1" location="apps/web/package.json:45">
P0: Major version bump from `react-router-dom` v6 to v7 without corresponding code changes. React Router v7 has significant breaking changes from v6 (it merged with Remix). The codebase heavily uses v6 APIs (`createBrowserRouter`, `RouterProvider`, `redirect`, `useNavigate`, `useSearchParams`, `Link`, `Outlet`, etc.) across many files. This bump will very likely break the application at build or runtime. Consider following the [official v6→v7 migration guide](https://reactrouter.com/upgrading/v6) or pin to a safe v6 patch instead.</violation>

<violation number="2" location="apps/web/package.json:69">
P0: Major version bump to Vite 7 while `vite-plugin-eslint` (^1.8.1) remains unchanged. `vite-plugin-eslint` is unmaintained and used in `vite.config.ts`. It is very unlikely to be compatible with Vite 7. `@vitejs/plugin-react` (^4.3.4) may also need a major version update for Vite 7 compatibility. This will likely break the build. Consider removing `vite-plugin-eslint` (using ESLint separately) and verifying plugin compatibility, or pin to a safe Vite 6 patch.</violation>
</file>

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

Comment thread apps/web/package.json Outdated
Comment thread apps/web/package.json Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
apps/api/src/app/billing/resolvers/mutations/login-to-stripe.mutation.ts (1)

18-18: Prefer ?? over || for explicit null coalescing.

The intent — ensuring null is returned instead of undefined for GraphQL resolver correctness — is valid. However, || falls back to null for any falsy value (including an empty string ""), whereas ?? only handles null | undefined, which is the actual semantic here.

♻️ Proposed refactor
-    return session?.url || null;
+    return session?.url ?? null;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/billing/resolvers/mutations/login-to-stripe.mutation.ts` at
line 18, The current return uses the falsy operator on session?.url (return
session?.url || null) which incorrectly converts empty strings to null; change
it to the nullish coalescing operator so it returns session?.url ?? null
instead, preserving empty-string values while still converting undefined to null
for the GraphQL resolver.
apps/api/src/prisma.ts (1)

90-94: Explicit as T cast is correct but remains unchecked at runtime.

The added as T on the JSON.parse branch is a pure compile-time change that makes both branches of the ternary consistently typed — no runtime impact. However, JsonValue includes null, booleans, numbers, and arrays; for any of those, isObject returns false and the code falls into JSON.parse(value as string). If JSON.parse returns something that is not Record<string, any> (e.g., null, a primitive, or an array), the as T cast silently lies to the type system and callers get unexpected runtime values with no TypeScript error.

Consider a lightweight runtime guard, even if just an assertion:

🛡️ Optional runtime guard
 export const jsonObject = <T extends Record<string, any>>(
   value: string | object | JsonValue
 ): T => {
-  return isObject(value) ? (value as T) : (JSON.parse(value as string) as T);
+  if (isObject(value)) return value as T;
+  const parsed = JSON.parse(value as string);
+  if (!isObject(parsed)) throw new TypeError(`jsonObject: expected an object, got ${typeof parsed}`);
+  return parsed as T;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/prisma.ts` around lines 90 - 94, The jsonObject function
currently casts JSON.parse(...) to T without verifying the runtime shape; modify
jsonObject (and use the existing isObject) to perform a runtime check after
parsing: parse the string, assert/throw if the result is not an object (e.g.,
null or Array) so you never return a non-object as T, and only return the parsed
value cast to T once the shape-check passes; update the JSON.parse branch to
include this lightweight guard and a clear error message referencing
jsonObject/isObject/JsonValue.
apps/api/src/app/auth/services/auth.service.ts (1)

64-67: as SignOptions blanket cast may silently accept an incompatible expiresIn type.

Casting the whole options object literal suppresses any type mismatch on config.auth.jwt.expiresIn. If the config type is wider than SignOptions['expiresIn'] (e.g. string | undefined), the cast hides it. Prefer narrowing the cast to the value only, or constraining the config type at its definition.

♻️ Tighter alternative
  const accessToken = jwt.sign(payload, config.auth.jwt.secret, {
-   expiresIn: config.auth.jwt.expiresIn,
- } as SignOptions);
+   expiresIn: config.auth.jwt.expiresIn as SignOptions["expiresIn"],
+ });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/auth/services/auth.service.ts` around lines 64 - 67, The
code in signJwtToken uses a blanket cast on the options object which can mask an
incompatible type for config.auth.jwt.expiresIn; update signJwtToken so you do
not cast the entire object to SignOptions — instead validate or coerce
config.auth.jwt.expiresIn to a SignOptions['expiresIn'] (e.g. ensure it's string
| number and not undefined) and only cast or pass the validated value (or
provide a typed local variable like const expiresIn: SignOptions['expiresIn'] =
/* validated value */) into jwt.sign; alternatively tighten the config type at
its source so config.auth.jwt.expiresIn already matches
SignOptions['expiresIn'].
apps/web/package.json (1)

45-45: react-router-dom is deprecated in v7 — consider migrating to react-router.

In v7, react-router-dom is no longer needed as the packages have been unified. React Router v7 re-exports everything from react-router, making react-router-dom a compatibility shim. You can safely uninstall react-router-dom from package.json and update all imports to use react-router instead (79 imports across the codebase). Runtime behavior is identical, but the official upgrade guide recommends this migration. Individual import changes are straightforward; start by installing react-router and systematically updating import statements from react-router-dom to react-router.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/package.json` at line 45, package.json currently lists the
deprecated dependency "react-router-dom"; remove "react-router-dom" from
dependencies, install "react-router" instead, and update all import sites that
reference react-router-dom to import from react-router (search for
"react-router-dom" and replace with "react-router"); ensure the app builds and
run tests to catch any remaining compatibility shims or named-export differences
and update any usage tied to BrowserRouter/HashRouter wrappers by importing the
same symbols from react-router if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/package.json`:
- Line 69: The engines.node range is too permissive for Vite 7 (vite in
package.json) and may allow Node 20.x < 20.19 which Vite 7 doesn't support;
update the root package.json "engines.node" value to a strict minimum such as
">=20.19.0 || >=22.12.0" (or ">=20.19" if you prefer short form) so Node.js
versions below 20.19 are excluded and Vite 7 will run reliably.

---

Nitpick comments:
In `@apps/api/src/app/auth/services/auth.service.ts`:
- Around line 64-67: The code in signJwtToken uses a blanket cast on the options
object which can mask an incompatible type for config.auth.jwt.expiresIn; update
signJwtToken so you do not cast the entire object to SignOptions — instead
validate or coerce config.auth.jwt.expiresIn to a SignOptions['expiresIn'] (e.g.
ensure it's string | number and not undefined) and only cast or pass the
validated value (or provide a typed local variable like const expiresIn:
SignOptions['expiresIn'] = /* validated value */) into jwt.sign; alternatively
tighten the config type at its source so config.auth.jwt.expiresIn already
matches SignOptions['expiresIn'].

In `@apps/api/src/app/billing/resolvers/mutations/login-to-stripe.mutation.ts`:
- Line 18: The current return uses the falsy operator on session?.url (return
session?.url || null) which incorrectly converts empty strings to null; change
it to the nullish coalescing operator so it returns session?.url ?? null
instead, preserving empty-string values while still converting undefined to null
for the GraphQL resolver.

In `@apps/api/src/prisma.ts`:
- Around line 90-94: The jsonObject function currently casts JSON.parse(...) to
T without verifying the runtime shape; modify jsonObject (and use the existing
isObject) to perform a runtime check after parsing: parse the string,
assert/throw if the result is not an object (e.g., null or Array) so you never
return a non-object as T, and only return the parsed value cast to T once the
shape-check passes; update the JSON.parse branch to include this lightweight
guard and a clear error message referencing jsonObject/isObject/JsonValue.

In `@apps/web/package.json`:
- Line 45: package.json currently lists the deprecated dependency
"react-router-dom"; remove "react-router-dom" from dependencies, install
"react-router" instead, and update all import sites that reference
react-router-dom to import from react-router (search for "react-router-dom" and
replace with "react-router"); ensure the app builds and run tests to catch any
remaining compatibility shims or named-export differences and update any usage
tied to BrowserRouter/HashRouter wrappers by importing the same symbols from
react-router if needed.

Comment thread apps/web/package.json Outdated
@sweetr-dev sweetr-dev Bot added large Large PR - Consider splitting up into smaller PRs to reduce risk and review time and removed small Small PR - Quick and easy to review labels Feb 22, 2026
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

19 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread apps/api/src/app/sync-batch/services/sync-batch.service.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (2)
packages/graphql-types/api.ts (1)

1445-1451: ⚠️ Potential issue | 🔴 Critical

AsyncIterable causes compilation failure — add "lib": ["ES2018"] to packages/graphql-types/tsconfig.json.

Line 1450 references AsyncIterable, which requires ES2018+ library support. The packages/graphql-types/tsconfig.json lacks both "lib" and "target" compiler options, causing TypeScript to default to ES3 and fail with: Cannot find name 'AsyncIterable'. Do you need to change your target library?

Add "lib": ["ES2018"] (or higher) to the compilerOptions in packages/graphql-types/tsconfig.json. The auto-generated code from GraphQL codegen requires this.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/graphql-types/api.ts` around lines 1445 - 1451, The generated type
SubscriptionSubscribeFn uses AsyncIterable which requires ES2018+ lib support;
update the package's tsconfig compilerOptions to include "lib": ["ES2018"] (or a
higher ES version) so TypeScript recognizes AsyncIterable (alternatively set a
target that provides the appropriate libs). Ensure the change is saved to the
package's tsconfig.json under compilerOptions so GraphQL codegen output like
SubscriptionSubscribeFn and related AsyncIterable references compile correctly.
apps/web/src/api/environments.api.ts (1)

55-62: ⚠️ Potential issue | 🟠 Major

Change options to a required parameter to enforce TypeScript validation of initialPageParam and getNextPageParam.

The current signature options?: Optional<...> allows callers to omit the entire parameter, bypassing TypeScript's type checking for the required fields within UseInfiniteQueryOptions. In TanStack Query v5, initialPageParam is mandatory and has no implicit default; omitting it causes infinite scroll to fail silently at runtime.

The Optional<UseInfiniteQueryOptions<...>, "queryKey"> type correctly removes the queryKey requirement, but only if the parameter itself is passed. Making the parameter optional defeats this enforcement. Remove the ?: from the parameter to require callers to provide options:

🔧 Fix
 export const useEnvironmentsInfiniteQuery = (
   args: EnvironmentsQueryVariables,
-  options?: Optional<
+  options: Optional<
     UseInfiniteQueryOptions<
       EnvironmentsQuery,
       DefaultError,
       InfiniteData<EnvironmentsQuery>
     >,
     "queryKey"
   >,
 ) =>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/api/environments.api.ts` around lines 55 - 62, The options
parameter is currently optional which allows callers to omit required fields
like initialPageParam and getNextPageParam; make the parameter required by
removing the optional marker so the signature uses options:
Optional<UseInfiniteQueryOptions<EnvironmentsQuery, DefaultError,
InfiniteData<EnvironmentsQuery>>, "queryKey"> (i.e., delete the "?:") in the
function that declares options so TypeScript enforces supplying
initialPageParam/getNextPageParam (update any call sites as needed to pass an
options object).
🧹 Nitpick comments (2)
packages/graphql-types/frontend/gql.ts (1)

16-86: LGTM — typed Documents map is a clean improvement.

The type Documents constraint on documents gives each string-literal key the precise TypedDocumentNode<Query, Variables> type (via typeof types.XDocument), which propagates correctly through the (typeof documents)[source] overload return types. All 69 operation entries are consistent across the type map, the runtime map, and the overloads.

One optional improvement: type Documents is currently module-local. Exporting it allows downstream consumers to reference the full map type without resorting to typeof documents.

♻️ Optional: export the `Documents` type
-type Documents = {
+export type Documents = {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/graphql-types/frontend/gql.ts` around lines 16 - 86, The Documents
type is currently module-local; export it so downstream consumers can reference
the full map type without using typeof documents—update the declaration of the
type named Documents (in packages/graphql-types/frontend/gql.ts) to be exported
(i.e., export type Documents = { ... }) and ensure any imports elsewhere that
should reference this mapped type use the exported Documents symbol.
apps/web/src/api/environments.api.ts (1)

24-24: Import change is valid; type design is permissive but currently used correctly.

The import of Optional from utility-types instead of @tanstack/react-query is appropriate. The Optional<T, K> type from utility-types (which expands to Omit<T, K> & Partial<Pick<T, K>>) is semantically equivalent and reflects that Optional is no longer exported from TanStack Query v5.

The optional parameter design in useEnvironmentsInfiniteQuery is permissive—it allows callers to omit options entirely, even though initialPageParam and getNextPageParam are required within UseInfiniteQueryOptions for v5. However, the actual caller in apps/web/src/app/systems/environments/page.tsx (lines 39–52) explicitly provides both fields, so there is no current breakage. If other callers omit the parameter, the hook would fail at runtime. Consider tightening the type signature to options: (required) or using Partial<UseInfiniteQueryOptions> (like useEnvironmentOptionsQuery does) to prevent this footgun.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/api/environments.api.ts` at line 24, The hook currently imports
Optional from utility-types and declares useEnvironmentsInfiniteQuery with a
permissive optional options parameter which can omit required infinite-query
fields; update the hook signature to prevent runtime footguns by either making
the options parameter required (i.e., require UseInfiniteQueryOptions with
initialPageParam and getNextPageParam) or change its type to
Partial<UseInfiniteQueryOptions> (matching the pattern used in
useEnvironmentOptionsQuery) so callers must explicitly provide or intentionally
omit those required fields; modify the function declaration for
useEnvironmentsInfiniteQuery and its type import usage accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@apps/web/src/api/environments.api.ts`:
- Around line 55-62: The options parameter is currently optional which allows
callers to omit required fields like initialPageParam and getNextPageParam; make
the parameter required by removing the optional marker so the signature uses
options: Optional<UseInfiniteQueryOptions<EnvironmentsQuery, DefaultError,
InfiniteData<EnvironmentsQuery>>, "queryKey"> (i.e., delete the "?:") in the
function that declares options so TypeScript enforces supplying
initialPageParam/getNextPageParam (update any call sites as needed to pass an
options object).

In `@packages/graphql-types/api.ts`:
- Around line 1445-1451: The generated type SubscriptionSubscribeFn uses
AsyncIterable which requires ES2018+ lib support; update the package's tsconfig
compilerOptions to include "lib": ["ES2018"] (or a higher ES version) so
TypeScript recognizes AsyncIterable (alternatively set a target that provides
the appropriate libs). Ensure the change is saved to the package's tsconfig.json
under compilerOptions so GraphQL codegen output like SubscriptionSubscribeFn and
related AsyncIterable references compile correctly.

---

Nitpick comments:
In `@apps/web/src/api/environments.api.ts`:
- Line 24: The hook currently imports Optional from utility-types and declares
useEnvironmentsInfiniteQuery with a permissive optional options parameter which
can omit required infinite-query fields; update the hook signature to prevent
runtime footguns by either making the options parameter required (i.e., require
UseInfiniteQueryOptions with initialPageParam and getNextPageParam) or change
its type to Partial<UseInfiniteQueryOptions> (matching the pattern used in
useEnvironmentOptionsQuery) so callers must explicitly provide or intentionally
omit those required fields; modify the function declaration for
useEnvironmentsInfiniteQuery and its type import usage accordingly.

In `@packages/graphql-types/frontend/gql.ts`:
- Around line 16-86: The Documents type is currently module-local; export it so
downstream consumers can reference the full map type without using typeof
documents—update the declaration of the type named Documents (in
packages/graphql-types/frontend/gql.ts) to be exported (i.e., export type
Documents = { ... }) and ensure any imports elsewhere that should reference this
mapped type use the exported Documents symbol.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

20 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread apps/api/src/app/sync-batch/services/sync-batch.service.ts
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

99 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread apps/api/src/app/sync-batch/services/sync-batch.service.ts
coderabbitai[bot]
coderabbitai Bot previously approved these changes Feb 22, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
apps/api/package.json (1)

32-32: ⚠️ Potential issue | 🟡 Minor

Upgrade @bull-board/express to a version with explicit Express 5 support.

@bull-board/express@^6.7.10 does not explicitly declare Express 5 support. The bull-board project added Express 5 as optional support around v6.5.4, but v6.7.10 (released Feb 27, 2025) makes no mention of Express 5 in its release notes. Versions v6.12.7+ declare dual support (express: ^4.21.1 || ^5.0.0), and v6.19.0+ targets Express 5 directly. Either upgrade to v6.19.0+ or v6.12.7+ to ensure explicit Express 5 compatibility, or verify the v6.7.10 peer dependencies support Express 5 before shipping.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/package.json` at line 32, The package.json currently pins
"@bull-board/express": "^6.7.10" which does not explicitly declare Express 5
support; update the dependency entry for "@bull-board/express" to a version that
declares Express 5 compatibility (for example set the version to "6.19.0" or
"6.12.7" or higher), then reinstall dependencies and regenerate the lockfile
(npm/yarn/pnpm install) and run tests; ensure references to
"@bull-board/express" in package.json and any CI install steps are updated so
the new version is used.
🧹 Nitpick comments (2)
apps/api/src/app/email/services/email-template.service.ts (1)

13-17: id is a queue/job concern — consider separating it from the email template interface.

The id field (used as a bullmq job deduplication key, e.g., "initial-sync-complete") is orthogonal to what BuildEmailTemplate describes — an email's type and rendering props. Coupling a queue-level concept here reduces interface cohesion and forces all template callers to be aware of job IDs.

A cleaner design would carry id at the job/envelope level only:

// Queue job payload — keeps queue concerns separate
interface SendEmailJob {
  id?: string;          // bullmq deduplication key
  template: BuildEmailTemplate;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/app/email/services/email-template.service.ts` around lines 13 -
17, BuildEmailTemplate currently includes a queue-specific id which breaks
cohesion; remove the id property from the BuildEmailTemplate interface (leaving
EmailTemplate and EmailTemplateProps[EmailTemplate] intact) and introduce a
separate SendEmailJob envelope that has an optional id?: string for bullmq
deduplication and a template: BuildEmailTemplate field; then update any
enqueueing or job-creation sites that currently pass an object shaped like
BuildEmailTemplate to instead wrap it in SendEmailJob so queue concerns live
only at the job/envelope level.
apps/web/package.json (1)

70-70: vite-plugin-eslint removal degrades real-time lint feedback during development.

Removing the plugin means ESLint violations are no longer surfaced inline during vite dev — only the standalone lint script catches them. Consider a TypeScript-aware alternative such as vite-plugin-checker (which supports ESLint and TS diagnostics) to restore in-editor/dev-server lint feedback.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/package.json` at line 70, The removal of vite-plugin-eslint
eliminated inline ESLint feedback during `vite dev`; restore dev-time linting by
adding a TypeScript-aware dev plugin such as `vite-plugin-checker` as a
devDependency in package.json (alongside keeping the existing `lint` script),
then configure it in your Vite config file (vite.config.ts or vite.config.js) to
enable ESLint and TypeScript diagnostics (reference the plugin name
`vite-plugin-checker` and ensure you call its setup in the Vite plugins array),
so the dev server surfaces ESLint/TS errors in real time.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@certs/devcert.js`:
- Around line 6-12: The catch block around require("devcert") should
discriminate MODULE_NOT_FOUND from other errors: when require("devcert") throws,
check err.code === 'MODULE_NOT_FOUND' (or that the error message indicates
missing module) and only then print the "devcert is not installed" message and
exit; for any other error from the module (syntax/runtime), rethrow or log the
actual error so the real failure is visible. Update the try/catch around the
require in devcert.js to inspect the thrown error (e.g., err) and handle the two
cases accordingly.

In `@package.json`:
- Line 37: The current override entry "ajv": ">=6.14.0" allows ajv v8 which
breaks packages expecting the v6 API; change the override value for the ajv
entry to constrain it to semver v6 (for example ">=6.14.0 <7.0.0" or "^6.14.0")
so transitive deps like eslint and `@eslint/eslintrc` continue to resolve ajv v6;
update the package.json override key "ajv" accordingly and run install to verify
no v7/v8 is pulled in.
- Line 36: The minimatch dependency is pinned with an open-ended range
("minimatch": ">=10.2.1") which can pull future major versions and break
transitive consumers; change that entry to the exact safe patch "10.2.2" and
then regenerate the lockfile (npm/yarn/pnpm install) so the lockfile and
node_modules reflect the pinned version; update whichever file contains the
dependency entry ("minimatch" in package.json) and commit the updated lockfile.

---

Outside diff comments:
In `@apps/api/package.json`:
- Line 32: The package.json currently pins "@bull-board/express": "^6.7.10"
which does not explicitly declare Express 5 support; update the dependency entry
for "@bull-board/express" to a version that declares Express 5 compatibility
(for example set the version to "6.19.0" or "6.12.7" or higher), then reinstall
dependencies and regenerate the lockfile (npm/yarn/pnpm install) and run tests;
ensure references to "@bull-board/express" in package.json and any CI install
steps are updated so the new version is used.

---

Nitpick comments:
In `@apps/api/src/app/email/services/email-template.service.ts`:
- Around line 13-17: BuildEmailTemplate currently includes a queue-specific id
which breaks cohesion; remove the id property from the BuildEmailTemplate
interface (leaving EmailTemplate and EmailTemplateProps[EmailTemplate] intact)
and introduce a separate SendEmailJob envelope that has an optional id?: string
for bullmq deduplication and a template: BuildEmailTemplate field; then update
any enqueueing or job-creation sites that currently pass an object shaped like
BuildEmailTemplate to instead wrap it in SendEmailJob so queue concerns live
only at the job/envelope level.

In `@apps/web/package.json`:
- Line 70: The removal of vite-plugin-eslint eliminated inline ESLint feedback
during `vite dev`; restore dev-time linting by adding a TypeScript-aware dev
plugin such as `vite-plugin-checker` as a devDependency in package.json
(alongside keeping the existing `lint` script), then configure it in your Vite
config file (vite.config.ts or vite.config.js) to enable ESLint and TypeScript
diagnostics (reference the plugin name `vite-plugin-checker` and ensure you call
its setup in the Vite plugins array), so the dev server surfaces ESLint/TS
errors in real time.

Comment thread certs/devcert.js
Comment thread package.json Outdated
Comment thread package.json Outdated
sweetrdev
sweetrdev previously approved these changes Feb 22, 2026
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

99 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread apps/web/src/root.tsx
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

99 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread apps/api/src/app/sync-batch/services/sync-batch.service.ts
@waltergalvao waltergalvao merged commit 8e88381 into main Feb 22, 2026
11 checks passed
@waltergalvao waltergalvao deleted the fix/2026-02-npm-vulnerabilities branch February 22, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

large Large PR - Consider splitting up into smaller PRs to reduce risk and review time

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants