Skip to content

refactor: zod#37

Merged
kzndotsh merged 34 commits intomainfrom
refactor/zod
Feb 2, 2026
Merged

refactor: zod#37
kzndotsh merged 34 commits intomainfrom
refactor/zod

Conversation

@kzndotsh
Copy link
Contributor

@kzndotsh kzndotsh commented Feb 1, 2026

Description

Changes

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test addition or update

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed

Test Steps

Checklist

  • Code follows the project's style guidelines
  • Self-review of code performed
  • Comments added for complex code
  • Documentation updated (if applicable)
  • No new warnings generated
  • Tests added/updated and passing
  • All CI checks passing
  • Dependencies updated (if applicable)

Related Issues

Closes #36

Screenshots (if applicable)

Additional Notes

Summary by Sourcery

Adopt shared Zod schemas across integrations to infer types and centralize validation logic.

Enhancements:

  • Route IRC and XMPP integration types and validation through shared Zod schemas for a single source of truth.

Build:

  • Add drizzle-zod dependency to support schema generation from Drizzle tables.

Documentation:

  • Document Zod schema standards and layering approach in the new docs/ZOD.md guide.

- Install drizzle-zod@0.8.3 for schema generation from database
- Add drizzle-zod schema generation to IRC and XMPP database schemas
- Create centralized schema directory (src/shared/schemas/)
  - Add reusable schema utilities
  - Add IRC validation schemas with custom nick validation
  - Add XMPP validation schemas with username validation
- Migrate inline schemas from implementation files to centralized location
- Convert TypeScript interfaces to Zod-inferred types
- Fix metadata type compatibility with transform functions
- Disable barrel file linting rules in biome.jsonc for better DX

Architecture: Database (Drizzle) → drizzle-zod → Custom Schemas → TypeScript Types

All types now inferred from Zod schemas, schemas generated from or extend
database schemas, and database is the single source of truth.

Verification:
- Type check: ✓ Passed
- Linter: ✓ Passed (exit code 0)
Remove all biome-ignore comments for noBarrelFile and noNamespaceImport
rules that were disabled in biome.jsonc. These suppression comments
are no longer needed and were causing lint warnings.

Files cleaned:
- src/features/auth/lib/config.ts
- src/features/integrations/lib/irc/implementation.ts
- src/features/integrations/lib/irc/unreal/client.ts
- src/features/integrations/components/integration-management.tsx
- src/app/(dashboard)/app/integrations/integrations-content.tsx
- src/features/integrations/api/index.ts
- src/features/user/api/index.ts
- src/features/admin/api/index.ts
- src/shared/api/index.ts
- src/shared/types/api.ts
- src/app/metadata.ts

Linter now passes with zero warnings.
Add ZOD.md to docs/ directory covering:
- Database First architecture and three-layer system
- When to use Drizzle schemas, drizzle-zod, custom Zod schemas, and TypeScript types
- Directory structure and organization patterns
- Best practices for schema design and validation
- Detailed examples for CRUD operations, complex validation, and nested objects
- Migration guide for converting existing code to the new pattern
- Integration with existing documentation (API.md, ARCHITECTURE.md, etc.)

This documentation provides a complete reference for developers working with
schemas and validation in the Portal application, ensuring consistent patterns
and maintaining the single source of truth principle.
@kzndotsh kzndotsh linked an issue Feb 1, 2026 that may be closed by this pull request
@sourcery-ai
Copy link

sourcery-ai bot commented Feb 1, 2026

Reviewer's Guide

Refactors IRC and XMPP integration types and validation to rely on shared Zod schemas generated from Drizzle sources, centralizing schema definitions, updating integrations to consume the shared schemas, and documenting the new standards while adding necessary tooling dependencies.

Sequence diagram for IRC account creation using shared Zod schema

sequenceDiagram
  actor Client
  participant IrcIntegration
  participant CreateIrcAccountRequestSchema
  participant IrcDb as ircAccount
  participant AthemeClient

  Client->>IrcIntegration: createAccount(input)
  IrcIntegration->>CreateIrcAccountRequestSchema: safeParse(input)
  CreateIrcAccountRequestSchema-->>IrcIntegration: result(success or error)

  alt validation_error
    IrcIntegration-->>Client: throw Error(validation message)
  else validation_success
    IrcIntegration->>IrcIntegration: generateIrcPassword()
    IrcIntegration->>AthemeClient: registerNick(validated.nick, password)
    AthemeClient-->>IrcIntegration: registration result
    IrcIntegration->>IrcDb: insert new row
    IrcDb-->>IrcIntegration: created account record
    IrcIntegration-->>Client: IrcAccount with temporaryPassword
  end
Loading

Class diagram for updated IRC and XMPP integration schemas and types

classDiagram
  class ircAccount {
    +id : text
    +userId : text
    +nick : text
    +status : enum
    +metadata : jsonb
  }

  class selectIrcAccountSchema {
    +shape from ircAccount
  }

  class insertIrcAccountSchema {
    +shape from ircAccount
  }

  class IrcAccountStatusSchema {
    +values : active,pending,suspended,deleted
  }

  class UpdateIrcAccountStatusSchema {
    +values : active,pending,suspended
  }

  class CreateIrcAccountRequestSchema {
    +nick : string
  }

  class UpdateIrcAccountRequestSchema {
    +status : UpdateIrcAccountStatusSchema?
    +metadata : Record_string_unknown?
    +nick : string?
  }

  class IrcAccountSchema {
    +all fields from selectIrcAccountSchema
    +integrationId : "irc"
    +temporaryPassword : string?
  }

  class IrcAccount {
  }

  class CreateIrcAccountRequest {
  }

  class UpdateIrcAccountRequest {
  }

  class IrcAccountStatus {
  }

  class UpdateIrcAccountStatus {
  }

  class xmppAccount {
    +id : text
    +userId : text
    +username : text
    +jid : text
    +status : enum
    +metadata : jsonb
  }

  class selectXmppAccountSchema {
    +shape from xmppAccount
  }

  class insertXmppAccountSchema {
    +shape from xmppAccount
  }

  class XmppAccountStatusSchema {
    +values : active,suspended,deleted
  }

  class UpdateXmppAccountStatusSchema {
    +values : active,suspended
  }

  class CreateXmppAccountRequestSchema {
    +username : string?
  }

  class UpdateXmppAccountRequestSchema {
    +status : UpdateXmppAccountStatusSchema?
    +metadata : Record_string_unknown?
    +username : string?
  }

  class XmppAccountSchema {
    +all fields from selectXmppAccountSchema
    +integrationId : "xmpp"
  }

  class XmppAccount {
  }

  class CreateXmppAccountRequest {
  }

  class UpdateXmppAccountRequest {
  }

  class XmppAccountStatus {
  }

  class UpdateXmppAccountStatus {
  }

  ircAccount <.. selectIrcAccountSchema : based on
  ircAccount <.. insertIrcAccountSchema : based on

  selectIrcAccountSchema <.. IrcAccountSchema : extends

  IrcAccountStatusSchema <.. IrcAccountStatus : z.infer
  UpdateIrcAccountStatusSchema <.. UpdateIrcAccountStatus : z.infer
  CreateIrcAccountRequestSchema <.. CreateIrcAccountRequest : z.infer
  UpdateIrcAccountRequestSchema <.. UpdateIrcAccountRequest : z.infer
  IrcAccountSchema <.. IrcAccount : z.infer

  xmppAccount <.. selectXmppAccountSchema : based on
  xmppAccount <.. insertXmppAccountSchema : based on

  selectXmppAccountSchema <.. XmppAccountSchema : extends

  XmppAccountStatusSchema <.. XmppAccountStatus : z.infer
  UpdateXmppAccountStatusSchema <.. UpdateXmppAccountStatus : z.infer
  CreateXmppAccountRequestSchema <.. CreateXmppAccountRequest : z.infer
  UpdateXmppAccountRequestSchema <.. UpdateXmppAccountRequest : z.infer
  XmppAccountSchema <.. XmppAccount : z.infer
Loading

File-Level Changes

Change Details Files
Integration type definitions now infer from shared Zod schemas for single-source-of-truth typing.
  • In IRC and XMPP type modules, replace manual interfaces and unions with z.infer typings backed by shared schemas.
  • Import shared Create/Update request and status schemas to maintain consistency across integrations.
src/features/integrations/lib/irc/types.ts
src/features/integrations/lib/xmpp/types.ts
Integration implementations now validate requests using centralized shared schemas instead of local definitions.
  • Remove locally declared z.object schemas in IRC and XMPP implementations.
  • Use CreateIrcAccountRequestSchema and Update* schemas from shared/integrations for safeParse validation paths.
src/features/integrations/lib/irc/implementation.ts
src/features/integrations/lib/xmpp/implementation.ts
Database schema modules now expose drizzle-zod generated schemas to feed shared validation layer.
  • Add select/insert schema exports via createSelectSchema/createInsertSchema in IRC and XMPP Drizzle table definitions.
src/shared/db/schema/irc.ts
src/shared/db/schema/xmpp.ts
Introduced shared schema layer and utilities plus supporting documentation and dependency.
  • Add drizzle-zod dependency and lockfile updates.
  • Create shared schema modules for IRC/XMPP, schema utilities, and index exports.
  • Add comprehensive ZOD standards doc outlining architecture and guidelines.
package.json
pnpm-lock.yaml
src/shared/schemas/integrations/irc.ts
src/shared/schemas/integrations/xmpp.ts
src/shared/schemas/utils.ts
src/shared/schemas/index.ts
src/shared/schemas/integrations/index.ts
docs/ZOD.md
Clean up barrel exports by removing suppressed lint comments.
  • Delete biome-ignore comments guarding barrel files across app/api modules so lint passes without suppressions.
src/app/metadata.ts
src/features/admin/api/index.ts
src/features/integrations/api/index.ts
src/features/user/api/index.ts
src/shared/api/index.ts
src/shared/types/api.ts

Assessment against linked issues

Issue Objective Addressed Explanation
#36 Introduce shared Zod schemas (with inferred types) for the IRC and XMPP integrations to ensure a single source of truth.
#36 Update the IRC and XMPP integration implementations and type definitions to consume the new shared schemas instead of local, duplicated validators/interfaces.
#36 Augment the project with supporting infrastructure (documentation and dependencies) explaining and enabling the new Zod-centric workflow.

Possibly linked issues

  • #refactor: zod: PR implements the Zod refactor described in the issue by standardizing schemas and adding docs.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link

coderabbitai bot commented Feb 1, 2026

Warning

Rate limit exceeded

@kzndotsh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 44 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between acea9c0 and 85910dc.

📒 Files selected for processing (10)
  • docs/API.md
  • docs/INTEGRATIONS.md
  • docs/ZOD.md
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
  • src/app/api/admin/users/route.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/api/utils.ts
  • src/shared/schemas/user.ts
📝 Walkthrough

Walkthrough

Centralizes and publishes Zod schemas and drizzle-zod DB schemas; wires schemas into IRC/XMPP integrations, integration core, hooks, routes, and UI; adds request validation and richer API error handling; tightens biome linter rules; and adds extensive Zod + react-hook-form documentation, examples, and utilities. (46 words)

Changes

Cohort / File(s) Summary
Config & deps
biome.jsonc, package.json
Enable stricter biome performance rules with targeted overrides; add drizzle-zod and zod-validation-error dependencies.
Shared schema barrels & utils
src/shared/schemas/index.ts, src/shared/schemas/integrations/index.ts, src/shared/schemas/utils.ts
Add schema barrels and helper brandedString plus metadata/enum/uuid helpers.
IRC schemas & DB
src/shared/schemas/integrations/irc.ts, src/shared/db/schema/irc.ts
Add full IRC Zod schemas/types and drizzle-zod selectIrcAccountSchema/insertIrcAccountSchema.
XMPP schemas & DB
src/shared/schemas/integrations/xmpp.ts, src/shared/db/schema/xmpp.ts
Add full XMPP Zod schemas/types and drizzle-zod selectXmppAccountSchema/insertXmppAccountSchema.
Integration implementations & types
src/features/integrations/lib/irc/..., src/features/integrations/lib/xmpp/..., src/features/integrations/lib/irc/types.ts, src/features/integrations/lib/xmpp/types.ts
Replace local Zod schemas/types with shared modules; wire imported create/update/account schemas into integration classes and update parsing.
Integration core, types, hooks & API
src/features/integrations/lib/core/base.ts, src/features/integrations/lib/core/types.ts, src/features/integrations/api/integrations.ts, src/features/integrations/hooks/use-integration.ts, src/app/api/integrations/[integration]/accounts/route.ts
Make IntegrationBase/Integration generic over create/update input types and accept optional Zod schemas; propagate generics to API/hooks; validate POST bodies per-integration with schema fallback.
API validation & error handling
src/shared/schemas/user.ts, src/shared/api/utils.ts, src/app/api/*/route.ts (user/me, admin/users/*, integrations route)
Add user-related schemas; switch routes to schema.parse; extend APIError/handleAPIError to detect Zod errors and include details.
Integration UI & form changes
src/app/(dashboard)/app/integrations/integrations-content.tsx, src/features/integrations/components/integration-management.tsx
Pass create schemas and dynamic input names to IntegrationManagement; refactor input handling to react-hook-form with optional zodResolver and form-level validation.
DB/Schema barrels & minor exports
src/shared/db/schema/*, src/shared/schemas/*
Add drizzle-zod select/insert schema exports and new schema barrels for consumers.
Barrel comment removals
multiple index.ts/barrel files (src/.../api/index.ts, src/shared/api/index.ts, src/shared/types/api.ts, etc.)
Removed inline biome-ignore comments (cosmetic only).
Docs, skills & examples
docs/ZOD.md, .cursor/skills/react-hook-form-zod/*, .cursor/skills/zod/* (many files)
Add extensive Zod + react-hook-form documentation, skill guides, example templates, scripts, and plugin metadata (docs and examples only).
Tests update
tests/app/api/user/me/route.test.ts
Mock @/shared/schemas/user to align tests with schema usage.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is largely incomplete; only the 'Closes #' field and a Summary by Sourcery are filled in, while all other required sections remain as empty template placeholders. Complete all required sections: add a meaningful description, list specific changes, mark the type of change checkbox, describe testing performed, and complete the checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 55.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'refactor: zod' is vague and generic, using non-descriptive terms that don't convey the specific changes made in the pull request. Provide a more specific title that describes the primary change, such as 'refactor: adopt shared zod schemas for integration validation' or 'refactor: centralize integration type definitions via zod schemas'.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR objectives indicate the work addresses issue #36 (refactor: zod) with schema centralization, type routing through Zod, dependency updates, and documentation as specified in the PR summary.
Out of Scope Changes check ✅ Passed Changes include necessary linter configuration updates, documentation, cursor skill guides, and test infrastructure alongside core schema refactoring—all supporting the Zod adoption goal. No unrelated changes detected.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/zod

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.

@gemini-code-assist
Copy link

Summary of Changes

Hello @kzndotsh, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a robust and standardized approach to schema management by integrating drizzle-zod and centralizing Zod schema definitions. The changes ensure that database schemas are the primary source of truth, from which Zod schemas are generated for API validation, and TypeScript types are inferred for compile-time safety. This refactoring significantly enhances consistency, maintainability, and type safety across the application's data models and API interactions.

Highlights

  • New Zod Schema Standards Documentation: A comprehensive docs/ZOD.md file has been added, outlining the architecture, three-layer system (Drizzle, Zod, TypeScript), directory structure, usage guidelines, best practices, examples, and a migration guide for Zod schemas within the application.
  • Integration of drizzle-zod: The drizzle-zod library has been introduced and integrated, allowing for the automatic generation of Zod schemas directly from Drizzle ORM database schemas. This establishes the database as the single source of truth for data structure.
  • Centralized Zod Schema Definitions: Existing Zod schemas for IRC and XMPP integrations have been refactored and moved to a new centralized location (src/shared/schemas/), leveraging the drizzle-zod generated schemas and promoting reusability and consistency across the application.
  • Improved Type Safety and Validation: TypeScript types for integration entities (like IrcAccount and XmppAccount) are now inferred directly from the centralized Zod schemas, ensuring compile-time type safety that aligns with runtime validation rules. Manual interface definitions have been replaced.
  • Biome Linter Rule Adjustments: Several biome-ignore comments related to lint/performance/noBarrelFile and lint/performance/noNamespaceImport have been removed, indicating either that the underlying issues were resolved through refactoring or that linter rules were adjusted in biome.jsonc to accommodate specific patterns (e.g., for Sentry imports).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@sentry
Copy link

sentry bot commented Feb 1, 2026

Codecov Report

❌ Patch coverage is 23.43750% with 98 lines in your changes missing coverage. Please review.
✅ Project coverage is 13.34%. Comparing base (e75297d) to head (85910dc).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...p/api/integrations/[integration]/accounts/route.ts 0.00% 32 Missing ⚠️
...integrations/components/integration-management.tsx 0.00% 30 Missing ⚠️
src/shared/schemas/user.ts 0.00% 8 Missing ⚠️
...c/features/integrations/lib/xmpp/implementation.ts 0.00% 5 Missing ⚠️
src/app/api/admin/users/route.ts 0.00% 4 Missing ⚠️
src/features/integrations/hooks/use-integration.ts 0.00% 4 Missing ⚠️
src/shared/schemas/utils.ts 60.00% 4 Missing ⚠️
...shboard)/app/integrations/integrations-content.tsx 0.00% 3 Missing ⚠️
src/features/integrations/api/integrations.ts 0.00% 2 Missing ⚠️
src/shared/api/utils.ts 60.00% 2 Missing ⚠️
... and 4 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #37      +/-   ##
==========================================
+ Coverage   12.99%   13.34%   +0.34%     
==========================================
  Files         171      175       +4     
  Lines        4316     4383      +67     
  Branches     1176     1189      +13     
==========================================
+ Hits          561      585      +24     
- Misses       3755     3798      +43     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kzndotsh kzndotsh changed the title refactor: zod refactor: zod Feb 1, 2026
Copy link

@amazon-q-developer amazon-q-developer bot left a comment

Choose a reason for hiding this comment

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

Summary

This PR successfully implements a comprehensive Zod schema refactoring that establishes a "Database First" approach with proper type safety. The refactoring follows good architectural patterns by:

Strengths:

  • Adds drizzle-zod integration for generating base schemas from database tables
  • Creates a well-organized schema directory structure (src/shared/schemas/)
  • Implements proper type inference using z.infer<> for single source of truth
  • Includes comprehensive documentation in docs/ZOD.md
  • Updates biome configuration to handle barrel files appropriately
  • Removes duplicate schema definitions from implementation files

⚠️ Critical Issues Found:

  • 2 Logic Errors: Missing validation in update schemas for both IRC and XMPP integrations could allow invalid data to pass validation

The architectural approach is sound and the implementation is mostly correct. The documentation is excellent and will help future developers understand the patterns. Once the validation issues are addressed, this will be a solid foundation for type-safe API validation.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

export const UpdateIrcAccountRequestSchema = z.object({
status: UpdateIrcAccountStatusSchema.optional(),
metadata: z.record(z.string(), z.unknown()).optional(),
nick: z.string().optional(),

Choose a reason for hiding this comment

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

🛑 Logic Error: The nick field in UpdateIrcAccountRequestSchema lacks validation. While the implementation correctly rejects nick changes, the schema should either exclude the field entirely or apply the same validation as the create schema to prevent invalid data from passing validation.

Suggested change
nick: z.string().optional(),
nick: z
.string()
.trim()
.min(1, "Nick is required")
.max(
IRC_NICK_MAX_LENGTH,
`Nick must be ${IRC_NICK_MAX_LENGTH} characters or less`
)
.refine(
isValidIrcNick,
`Invalid nick. Use letters, digits, or [ ] \\ ^ _ \` { | } ~ - (max ${IRC_NICK_MAX_LENGTH} characters).`
)
.optional(),

export const UpdateXmppAccountRequestSchema = z.object({
status: UpdateXmppAccountStatusSchema.optional(),
metadata: z.record(z.string(), z.unknown()).optional(),
username: z.string().optional(),

Choose a reason for hiding this comment

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

🛑 Logic Error: The username field in UpdateXmppAccountRequestSchema lacks validation. This allows invalid usernames to pass schema validation, potentially causing runtime errors when the implementation processes the data.

Suggested change
username: z.string().optional(),
username: z
.string()
.trim()
.min(1)
.refine(
isValidXmppUsername,
"Invalid username format. Username must be alphanumeric with underscores, hyphens, or dots, and start with a letter or number."
)
.optional(),

Copy link

@sourcery-ai sourcery-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.

Hey - I've found 3 issues, and left some high level feedback:

  • The new IRC/XMPP type aliases in src/features/integrations/lib/*/types.ts now duplicate the inferred types already exported from src/shared/schemas/integrations/{irc,xmpp}.ts; consider importing and re-exporting those shared types instead to keep a single source of truth and avoid future drift.
  • In the new IRC/XMPP schemas you manually inline z.record(z.string(), z.unknown()).optional() for metadata; since you’ve introduced metadataSchema in src/shared/schemas/utils.ts, it would be cleaner and more consistent to reuse that helper in these schemas.
  • For XMPP, CreateXmppAccountRequestSchema.username includes isValidXmppUsername validation while UpdateXmppAccountRequestSchema.username is a bare z.string().optional(); if updates should obey the same format rules, consider reusing the same validation schema (or a shared helper) for both create and update.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new IRC/XMPP type aliases in `src/features/integrations/lib/*/types.ts` now duplicate the inferred types already exported from `src/shared/schemas/integrations/{irc,xmpp}.ts`; consider importing and re-exporting those shared types instead to keep a single source of truth and avoid future drift.
- In the new IRC/XMPP schemas you manually inline `z.record(z.string(), z.unknown()).optional()` for metadata; since you’ve introduced `metadataSchema` in `src/shared/schemas/utils.ts`, it would be cleaner and more consistent to reuse that helper in these schemas.
- For XMPP, `CreateXmppAccountRequestSchema.username` includes `isValidXmppUsername` validation while `UpdateXmppAccountRequestSchema.username` is a bare `z.string().optional()`; if updates should obey the same format rules, consider reusing the same validation schema (or a shared helper) for both create and update.

## Individual Comments

### Comment 1
<location> `src/shared/schemas/integrations/xmpp.ts:24-32` </location>
<code_context>
+ * Schema for creating an XMPP account via API
+ * Username is optional (will be generated from email if not provided)
+ */
+export const CreateXmppAccountRequestSchema = z.object({
+  username: z
+    .string()
+    .trim()
+    .min(1)
+    .refine(
+      isValidXmppUsername,
+      "Invalid username format. Username must be alphanumeric with underscores, hyphens, or dots, and start with a letter or number."
+    )
+    .optional(),
+});
</code_context>

<issue_to_address>
**issue:** The combination of `optional()` and `min(1)` changes how empty strings are handled for `username`.

With this schema, `undefined` is allowed (for auto-generation) but `""` now fails validation. If any existing callers send an empty string instead of omitting `username`, this will change behavior. If empty should be treated as "not provided", consider using `optionalNonEmptyStringSchema` from `shared/schemas/utils` or adding a transform to normalize `""` to `undefined`.
</issue_to_address>

### Comment 2
<location> `src/shared/schemas/integrations/xmpp.ts:40-43` </location>
<code_context>
+ * Schema for updating an XMPP account via API
+ * Only allows updating specific fields
+ */
+export const UpdateXmppAccountRequestSchema = z.object({
+  status: UpdateXmppAccountStatusSchema.optional(),
+  metadata: z.record(z.string(), z.unknown()).optional(),
+  username: z.string().optional(),
+});
+
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Update request schema does not apply the same validation as create for `username`.

`CreateXmppAccountRequestSchema` trims and validates `username` with `isValidXmppUsername`, but here it’s just `z.string().optional()`. If updates must follow the same username rules, reuse the same validation (or extract a shared helper) to keep create/update behavior consistent.

Suggested implementation:

```typescript
/**
 * Schema for updating an XMPP account via API
 * Only allows updating specific fields
 */
export const UpdateXmppAccountRequestSchema = z.object({
  status: UpdateXmppAccountStatusSchema.optional(),
  metadata: z.record(z.string(), z.unknown()).optional(),
  username: z
    .string()
    .trim()
    .refine(
      isValidXmppUsername,
      "Invalid username format. Username must be alphanumeric with underscores, hyphens, or dots, and start with a letter or number."
    )
    .optional(),
});

```

If `CreateXmppAccountRequestSchema` adds additional constraints (e.g. `.min(1, "Username is required")` or uses a shared `XmppUsernameSchema` helper), you should mirror that here instead of only copying `.trim().refine(...)`. Ideally, extract the shared username validation into a dedicated schema, e.g. `const XmppUsernameSchema = z.string().trim().refine(isValidXmppUsername, "...");`, then use `XmppUsernameSchema` in both create and update (`XmppUsernameSchema` for create, `XmppUsernameSchema.optional()` for update) to keep behavior fully consistent and DRY.
</issue_to_address>

### Comment 3
<location> `src/shared/schemas/utils.ts:21` </location>
<code_context>
+
+```typescript
+// Reusable schema utilities
+export const metadataSchema = z.record(z.string(), z.unknown()).optional();
+export const uuidSchema = z.string().uuid();
+export const nonEmptyStringSchema = z.string().min(1);
</code_context>

<issue_to_address>
**suggestion:** The new metadata helper isn’t used in the integration schemas that define metadata fields.

IRC and XMPP schemas still define `metadata: z.record(z.string(), z.unknown()).optional()` inline. Please switch them to use `metadataSchema` to remove duplication and keep JSONB handling consistent across modules.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request is a significant and valuable refactoring that introduces Zod for schema validation and type inference, centralizing this logic and improving type safety across the application. The introduction of drizzle-zod to generate base schemas from the database is an excellent step towards a single source of truth. The new documentation in docs/ZOD.md is thorough and will be very helpful for the team.

My review focuses on a few key areas to further improve the implementation:

  • Runtime Safety: Ensuring that jsonb fields are safely parsed at runtime instead of just being type-casted.
  • Configuration: Suggesting a more targeted approach to disabling linter rules to maintain long-term code quality.
  • Documentation: Aligning the examples in the new documentation with the safest patterns.

Overall, this is a great improvement to the codebase's architecture.

Comment on lines 66 to 70
.transform((data) => ({
...data,
// Transform metadata from unknown to proper type
metadata: data.metadata as Record<string, unknown> | undefined,
}));

Choose a reason for hiding this comment

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

high

The transform for metadata uses a type assertion (as Record<string, unknown> | undefined), which bypasses Zod's runtime validation and is unsafe. Since drizzle-zod infers jsonb columns as z.unknown().nullable(), you should parse the metadata to ensure it's a valid object or null/undefined.

You can create a reusable metadataSchema = z.record(z.string(), z.unknown()).nullable().optional() in utils.ts and import it here to keep the code DRY.

Suggested change
.transform((data) => ({
...data,
// Transform metadata from unknown to proper type
metadata: data.metadata as Record<string, unknown> | undefined,
}));
.transform((data) => ({
...data,
// Transform metadata from unknown to a validated type
metadata: z.record(z.string(), z.unknown()).nullable().optional().parse(data.metadata),
}));

Comment on lines 54 to 58
.transform((data) => ({
...data,
// Transform metadata from unknown to proper type
metadata: data.metadata as Record<string, unknown> | undefined,
}));

Choose a reason for hiding this comment

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

high

Similar to the IRC schema, the transform for metadata uses an unsafe type assertion. To ensure runtime type safety, you should parse the metadata field using a Zod schema. This ensures the data conforms to the expected shape at runtime, which is a key benefit of this refactor.

You can create a reusable metadataSchema = z.record(z.string(), z.unknown()).nullable().optional() in utils.ts and import it here to keep the code DRY.

Suggested change
.transform((data) => ({
...data,
// Transform metadata from unknown to proper type
metadata: data.metadata as Record<string, unknown> | undefined,
}));
.transform((data) => ({
...data,
// Transform metadata from unknown to a validated type
metadata: z.record(z.string(), z.unknown()).nullable().optional().parse(data.metadata),
}));

Comment on lines 8 to 15
"linter": {
"rules": {
"performance": {
"noBarrelFile": "off",
"noNamespaceImport": "off"
}
}
},

Choose a reason for hiding this comment

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

medium

Disabling performance-related linter rules like noBarrelFile and noNamespaceImport globally can hide potential performance issues in the future. While this change cleans up the codebase by removing many biome-ignore comments, a more targeted approach might be better for long-term maintainability. Consider re-enabling these rules and using Biome's overrides feature to disable them only for specific paths where they are intentionally violated (like src/shared/schemas/index.ts and for Sentry imports).

Comment on lines 283 to 287
.transform((data) => ({
...data,
// Transform metadata from unknown to proper type
metadata: data.metadata as Record<string, unknown> | undefined,
}));

Choose a reason for hiding this comment

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

medium

The example for handling jsonb fields uses a type assertion (as Record<string, unknown> | undefined), which bypasses Zod's runtime validation. To better align with the principles outlined in this document and promote safer patterns, it would be better to demonstrate parsing the metadata field. This ensures the data conforms to the expected shape at runtime.

Suggested change
.transform((data) => ({
...data,
// Transform metadata from unknown to proper type
metadata: data.metadata as Record<string, unknown> | undefined,
}));
// Safely parse metadata from unknown to a validated type
metadata: z.record(z.string(), z.unknown()).nullable().optional().parse(data.metadata),
}));

@kzndotsh kzndotsh self-assigned this Feb 1, 2026
Copy link

@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.

3 issues found across 25 files

Confidence score: 3/5

  • Update schemas in src/shared/schemas/integrations/irc.ts and src/shared/schemas/integrations/xmpp.ts are looser than create, allowing invalid nick/username values through update requests; this is a concrete user-facing data validation gap.
  • src/shared/schemas/utils.ts metadata schema contradicts its comment and rejects non-object JSON values, which could block legitimate JSONB inputs if arrays/primitives are expected.
  • Pay close attention to src/shared/schemas/integrations/irc.ts, src/shared/schemas/integrations/xmpp.ts, src/shared/schemas/utils.ts - ensure update validation and metadata JSON acceptance match intended constraints.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/shared/schemas/integrations/xmpp.ts">

<violation number="1" location="src/shared/schemas/integrations/xmpp.ts:43">
P2: UpdateXmppAccountRequestSchema accepts any string for username, which bypasses the validation enforced on create and can allow invalid usernames through update requests. Mirror the same validation used for creation to keep data consistent.</violation>
</file>

<file name="src/shared/schemas/integrations/irc.ts">

<violation number="1" location="src/shared/schemas/integrations/irc.ts:54">
P1: Missing validation for `nick` in update schema. The `CreateIrcAccountRequestSchema` validates nick with `.trim()`, `.min(1)`, `.max(IRC_NICK_MAX_LENGTH)`, and `.refine(isValidIrcNick)`, but this update schema accepts any string. Apply the same validation to prevent invalid nicks from being saved during updates.</violation>
</file>

<file name="src/shared/schemas/utils.ts">

<violation number="1" location="src/shared/schemas/utils.ts:21">
P2: The metadata schema only permits objects, but the comment indicates it should accept any JSON value. This will reject arrays/primitives/null in JSONB fields. Consider widening the schema (or update the comment if objects are the only allowed shape).</violation>
</file>

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

Copy link

@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

🤖 Fix all issues with AI agents
In `@docs/ZOD.md`:
- Around line 28-52: The fenced code blocks in the ZOD.md diagram and
directory-structure examples are missing a language identifier, triggering
markdownlint MD040; update each opening triple-backtick fence for the ASCII
diagram and the directory listing (the blocks shown around the Database Schema
diagram and the src/ listing) to include a language token like "text" or
"plaintext" (e.g., replace ``` with ```text) so markdownlint treats them as
plain text.

In `@src/shared/schemas/integrations/irc.ts`:
- Around line 51-55: UpdateIrcAccountRequestSchema currently accepts any string
for nick; change it to reuse the creation validator so updates follow the same
RFC1459, length and trim rules. Replace the plain z.string().optional() for the
nick property with the create-schema's nick validator (e.g., use
CreateIrcAccountRequestSchema.shape.nick.optional() or import the shared
IrcNickSchema used by the create schema) so both CreateIrcAccountRequestSchema
and UpdateIrcAccountRequestSchema enforce identical validation.

In `@src/shared/schemas/integrations/xmpp.ts`:
- Around line 40-44: UpdateXmppAccountRequestSchema currently allows any string
for username; change it to reuse the exact username validation from
CreateXmppAccountRequestSchema so updates run .trim(), .min(1) and the
isValidXmppUsername check. Locate UpdateXmppAccountRequestSchema and replace the
loose z.string().optional() for the username field with the same schema used in
CreateXmppAccountRequestSchema (or reference
CreateXmppAccountRequestSchema.shape.username and make it optional) so both
create and update use identical validation.
🧹 Nitpick comments (4)
biome.jsonc (2)

8-13: Avoid globally disabling noBarrelFile (conflicts with repo guidance).

Turning this rule off globally contradicts the “avoid barrel files” guidance and makes future violations invisible. Prefer a scoped override (specific directories) or targeted suppressions where the barrel is unavoidable, and document the exception. Based on learnings “Avoid barrel files (index files that re-export everything)”.


10-12: Consider scoping noNamespaceImport relaxations.

Namespace imports can hide unused members and hurt tree-shaking. If this is only needed for a few files, prefer per-path overrides or inline suppressions to avoid lowering the bar globally.

src/features/integrations/lib/xmpp/implementation.ts (1)

238-241: Consider providing more specific validation error messages.

The IRC implementation's createAccount (lines 55-58) extracts and surfaces the first Zod issue message for better developer/user feedback. The current generic "Invalid update request" message loses valuable validation details.

♻️ Proposed improvement for error messaging
     const parsed = UpdateXmppAccountRequestSchema.safeParse(input);
     if (!parsed.success) {
-      throw new Error("Invalid update request");
+      const msg =
+        parsed.error.issues[0]?.message ?? "Invalid update request";
+      throw new Error(msg);
     }
src/features/integrations/lib/irc/implementation.ts (1)

272-275: Consider consistent error handling with createAccount.

The createAccount method (lines 54-58) extracts specific Zod validation messages, while updateAccount uses a generic message. For consistency and better debugging:

♻️ Align error handling with createAccount pattern
     const parsed = UpdateIrcAccountRequestSchema.safeParse(input);
     if (!parsed.success) {
-      throw new Error("Invalid update request");
+      const msg =
+        parsed.error.issues[0]?.message ?? "Invalid update request";
+      throw new Error(msg);
     }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 11d4a59 and aec284c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (24)
  • biome.jsonc
  • docs/ZOD.md
  • package.json
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
  • src/app/metadata.ts
  • src/features/admin/api/index.ts
  • src/features/auth/lib/config.ts
  • src/features/integrations/api/index.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/irc/types.ts
  • src/features/integrations/lib/irc/unreal/client.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/features/user/api/index.ts
  • src/shared/api/index.ts
  • src/shared/db/schema/irc.ts
  • src/shared/db/schema/xmpp.ts
  • src/shared/schemas/index.ts
  • src/shared/schemas/integrations/index.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/shared/schemas/utils.ts
  • src/shared/types/api.ts
💤 Files with no reviewable changes (10)
  • src/features/auth/lib/config.ts
  • src/features/user/api/index.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
  • src/shared/types/api.ts
  • src/features/integrations/api/index.ts
  • src/features/integrations/lib/irc/unreal/client.ts
  • src/features/admin/api/index.ts
  • src/shared/api/index.ts
  • src/features/integrations/components/integration-management.tsx
  • src/app/metadata.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

**/*.{js,jsx,ts,tsx}: Use Sentry.captureException(error) to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected
Use Sentry.startSpan() function to create spans for meaningful actions within applications like button clicks, API calls, and function calls

Files:

  • src/shared/schemas/index.ts
  • src/shared/db/schema/xmpp.ts
  • src/shared/schemas/integrations/index.ts
  • src/shared/db/schema/irc.ts
  • src/shared/schemas/utils.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/features/integrations/lib/irc/types.ts
**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

When creating custom spans for API calls with Sentry.startSpan(), ensure the name and op properties are meaningful (e.g., op: "http.client" with descriptive names like GET /api/users/${userId}), and attach attributes based on relevant request information and metrics

Files:

  • src/shared/schemas/index.ts
  • src/shared/db/schema/xmpp.ts
  • src/shared/schemas/integrations/index.ts
  • src/shared/db/schema/irc.ts
  • src/shared/schemas/utils.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/features/integrations/lib/irc/types.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

**/*.{js,ts,jsx,tsx}: Import Sentry using import * as Sentry from "@sentry/nextjs" when using logs in NextJS projects
Reference the Sentry logger using const { logger } = Sentry when using logging functionality
Use logger.fmt as a template literal function to bring variables into structured logs, providing better log formatting and variable interpolation

Files:

  • src/shared/schemas/index.ts
  • src/shared/db/schema/xmpp.ts
  • src/shared/schemas/integrations/index.ts
  • src/shared/db/schema/irc.ts
  • src/shared/schemas/utils.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/features/integrations/lib/irc/types.ts
**/*.{css,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/tailwind-v4.mdc)

Use container query support with @container, @sm:, @md: for container-based breakpoints and @max-md: for max-width queries

Files:

  • src/shared/schemas/index.ts
  • src/shared/db/schema/xmpp.ts
  • src/shared/schemas/integrations/index.ts
  • src/shared/db/schema/irc.ts
  • src/shared/schemas/utils.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/features/integrations/lib/irc/types.ts
**/*.{ts,tsx,js,jsx,html}

📄 CodeRabbit inference engine (.cursor/rules/tailwind-v4.mdc)

**/*.{ts,tsx,js,jsx,html}: Use 3D transform utilities: transform-3d, rotate-x-*, rotate-y-*, rotate-z-*, scale-z-*, translate-z-*, perspective-*, and perspective-origin-*
Use linear gradient angles with bg-linear-45 syntax and gradient interpolation like bg-linear-to-r/oklch or bg-linear-to-r/srgb
Use conic and radial gradients with bg-conic and bg-radial-[at_25%_25%] utilities
Use inset-shadow-* and inset-ring-* utilities instead of deprecated shadow opacity utilities
Use field-sizing-content utility for auto-resizing textareas
Use scheme-light and scheme-dark utilities for color-scheme property
Use font-stretch-* utilities for variable font configuration
Chain variants together for composable variants (e.g., group-has-data-potato:opacity-100)
Use starting variant for @starting-style transitions
Use not-* variant for :not() pseudo-class (e.g., not-first:mb-4)
Use inert variant for styling elements with the inert attribute
Use nth-* variants: nth-3:, nth-last-5:, nth-of-type-4:, nth-last-of-type-6: for targeting specific elements
Use in-* variant as a simpler alternative to group-* without adding group class
Use open variant to support :popover-open pseudo-class
Use ** variant for targeting all descendants
Replace deprecated bg-opacity-* utilities with color values using slash notation (e.g., bg-black/50)
Replace deprecated text-opacity-* utilities with color values using slash notation (e.g., text-black/50)
Replace deprecated border-opacity-*, divide-opacity-* and similar opacity utilities with color slash notation
Use shadow-xs instead of shadow-sm and shadow-sm instead of shadow
Use drop-shadow-xs instead of drop-shadow-sm and drop-shadow-sm instead of drop-shadow
Use blur-xs instead of blur-sm and blur-sm instead of blur
Use rounded-xs instead of rounded-sm and rounded-sm instead of rounded
Use outline-hidden instead of outline-none for...

Files:

  • src/shared/schemas/index.ts
  • src/shared/db/schema/xmpp.ts
  • src/shared/schemas/integrations/index.ts
  • src/shared/db/schema/irc.ts
  • src/shared/schemas/utils.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/features/integrations/lib/irc/types.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/tanstack-query.mdc)

**/*.{ts,tsx}: Create QueryClient using getQueryClient() function that automatically handles server/client isolation (new instance per server request, singleton on client)
Always use the centralized query key factory from src/lib/api/query-keys.ts instead of creating keys manually
Include all variables used in queryFn in the query key to ensure proper cache management and query invalidation

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

**/*.{ts,tsx}: Use TypeScript strict mode with explicit types; prefer unknown over any
Use functional components and hooks in React code
Use selective imports over barrel exports for performance
Follow Next.js App Router conventions
Always await promises in async functions
Use semantic HTML and ARIA attributes for accessibility
Import authentication operations from @/auth module using barrel exports
Import database operations from @/db module using barrel exports
Import app configuration from @/config or @/config/app using barrel exports
Import UI components using direct imports from @/components/ui/* (e.g., @/components/ui/button)
Import custom hooks using direct imports from @/hooks/* (e.g., @/hooks/use-permissions)
Centralize major types in src/types/ directory: use @/types/auth, @/types/api, @/types/routes, @/types/email, @/types/common for imports
Import major constants from @/lib/utils/constants.ts: USER_ROLES, PERMISSIONS, HTTP_STATUS, API_ERROR_CODES, QUERY_CACHE, RATE_LIMIT, INTEGRATION_STATUSES, PAGINATION, VALIDATION_PATTERNS, MOBILE_BREAKPOINT, DATE_FORMATS
Use TanStack Query for all server state management and data fetching
Optimize images with next/image component instead of HTML img tags
Validate all input...

Files:

  • src/shared/schemas/index.ts
  • src/shared/db/schema/xmpp.ts
  • src/shared/schemas/integrations/index.ts
  • src/shared/db/schema/irc.ts
  • src/shared/schemas/utils.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/features/integrations/lib/irc/types.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{ts,tsx,js,jsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Use function components over class components
Call hooks at the top level only, never conditionally
Specify all dependencies in hook dependency arrays correctly
Use the key prop for elements in iterables (prefer unique IDs over array indices)
Nest children between opening and closing tags instead of passing as props in React components
Don't define components inside other components
Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, and use semantic elements instead of divs with roles
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Keep functions focused and under reasonable cognitive complexity limits
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Group related code together and separate concerns
Add `...

Files:

  • src/shared/schemas/index.ts
  • src/shared/db/schema/xmpp.ts
  • src/shared/schemas/integrations/index.ts
  • src/shared/db/schema/irc.ts
  • src/shared/schemas/utils.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/features/integrations/lib/irc/types.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Validate all inputs with Zod schemas
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import authentication operations from `@/auth` module using barrel exports

Applied to files:

  • src/shared/schemas/index.ts
  • src/shared/schemas/integrations/index.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import database operations from `@/db` module using barrel exports

Applied to files:

  • src/shared/schemas/index.ts
  • src/shared/schemas/integrations/index.ts
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Avoid barrel files (index files that re-export everything)

Applied to files:

  • src/shared/schemas/index.ts
  • biome.jsonc
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import app configuration from `@/config` or `@/config/app` using barrel exports

Applied to files:

  • src/shared/schemas/index.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Centralize major types in `src/types/` directory: use `@/types/auth`, `@/types/api`, `@/types/routes`, `@/types/email`, `@/types/common` for imports

Applied to files:

  • src/shared/schemas/index.ts
  • src/shared/schemas/integrations/index.ts
  • src/features/integrations/lib/irc/types.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Use selective imports over barrel exports for performance

Applied to files:

  • src/shared/schemas/index.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/lib/*/keys.ts : Define module environment variables using t3-env `createEnv` with Zod schemas in module-level `keys.ts` files

Applied to files:

  • src/shared/schemas/index.ts
  • docs/ZOD.md
  • src/shared/schemas/utils.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import major constants from `@/lib/utils/constants.ts`: `USER_ROLES`, `PERMISSIONS`, `HTTP_STATUS`, `API_ERROR_CODES`, `QUERY_CACHE`, `RATE_LIMIT`, `INTEGRATION_STATUSES`, `PAGINATION`, `VALIDATION_PATTERNS`, `MOBILE_BREAKPOINT`, `DATE_FORMATS`

Applied to files:

  • src/shared/schemas/index.ts
  • src/shared/schemas/utils.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Validate all inputs with Zod schemas

Applied to files:

  • src/shared/schemas/index.ts
  • docs/ZOD.md
  • src/shared/schemas/utils.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/features/integrations/lib/xmpp/types.ts
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/backend/**/*.{ts,tsx,js,jsx} : Mandatory Zod validation at boundaries in backend

Applied to files:

  • docs/ZOD.md
  • src/shared/schemas/utils.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use single quotes and no semicolons (enforced by Biome configuration)

Applied to files:

  • biome.jsonc
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/app/**/*.{tsx} : In Server Components, create a QueryClient per request using getServerQueryClient(), prefetch data in parallel with Promise.all(), and dehydrate using dehydrate(queryClient)

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
📚 Learning: 2026-01-15T06:15:18.973Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/sentry.mdc:0-0
Timestamp: 2026-01-15T06:15:18.973Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Import Sentry using `import * as Sentry from "sentry/nextjs"` when using logs in NextJS projects

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:15:18.973Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/sentry.mdc:0-0
Timestamp: 2026-01-15T06:15:18.973Z
Learning: Applies to {instrumentation-client.{js,ts},sentry.server.config.{js,ts},sentry.edge.config.{js,ts}} : In NextJS projects, perform client-side Sentry initialization in `instrumentation-client.(js|ts)`, server initialization in `sentry.server.config.ts`, and edge initialization in `sentry.edge.config.ts` - do not repeat initialization in other files

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/app/**/*.{tsx} : Perform auth checks using Better Auth's auth.api.getSession() in Server Components before prefetching data, and redirect if not authenticated

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/lib/api/server-queries.ts : Server-side query functions in src/lib/api/server-queries.ts must use direct database access via ORM instead of HTTP requests

Applied to files:

  • src/features/integrations/lib/xmpp/implementation.ts
🧬 Code graph analysis (6)
src/shared/schemas/integrations/irc.ts (2)
src/shared/db/schema/irc.ts (1)
  • selectIrcAccountSchema (55-55)
src/features/integrations/lib/irc/types.ts (5)
  • IrcAccountStatus (21-21)
  • UpdateIrcAccountStatus (50-52)
  • CreateIrcAccountRequest (33-35)
  • UpdateIrcAccountRequest (58-60)
  • IrcAccount (27-27)
src/features/integrations/lib/irc/implementation.ts (1)
src/shared/schemas/integrations/irc.ts (2)
  • CreateIrcAccountRequestSchema (32-45)
  • UpdateIrcAccountRequestSchema (51-55)
src/features/integrations/lib/xmpp/implementation.ts (1)
src/shared/schemas/integrations/xmpp.ts (1)
  • UpdateXmppAccountRequestSchema (40-44)
src/shared/schemas/integrations/xmpp.ts (3)
src/features/integrations/lib/xmpp/utils.ts (1)
  • isValidXmppUsername (28-41)
src/shared/db/schema/xmpp.ts (1)
  • selectXmppAccountSchema (57-57)
src/features/integrations/lib/xmpp/types.ts (5)
  • XmppAccountStatus (21-21)
  • UpdateXmppAccountStatus (41-43)
  • CreateXmppAccountRequest (33-35)
  • UpdateXmppAccountRequest (49-51)
  • XmppAccount (27-27)
src/features/integrations/lib/xmpp/types.ts (1)
src/shared/schemas/integrations/xmpp.ts (10)
  • XmppAccountStatus (61-61)
  • XmppAccountStatusSchema (12-16)
  • XmppAccount (71-71)
  • XmppAccountSchema (50-58)
  • CreateXmppAccountRequest (65-67)
  • CreateXmppAccountRequestSchema (24-34)
  • UpdateXmppAccountStatus (62-64)
  • UpdateXmppAccountStatusSchema (18-18)
  • UpdateXmppAccountRequest (68-70)
  • UpdateXmppAccountRequestSchema (40-44)
src/features/integrations/lib/irc/types.ts (1)
src/shared/schemas/integrations/irc.ts (10)
  • IrcAccountStatus (73-73)
  • IrcAccountStatusSchema (15-20)
  • IrcAccount (83-83)
  • IrcAccountSchema (61-70)
  • CreateIrcAccountRequest (77-79)
  • CreateIrcAccountRequestSchema (32-45)
  • UpdateIrcAccountStatus (74-76)
  • UpdateIrcAccountStatusSchema (22-26)
  • UpdateIrcAccountRequest (80-82)
  • UpdateIrcAccountRequestSchema (51-55)
🪛 markdownlint-cli2 (0.20.0)
docs/ZOD.md

[warning] 28-28: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 130-130: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Seer Code Review
🔇 Additional comments (9)
src/shared/db/schema/xmpp.ts (1)

11-12: LGTM — generated select/insert schemas are exported for reuse.
Please double-check that drizzle-zod v0.8.3’s createSelectSchema / createInsertSchema signatures align with this usage.

Also applies to: 56-58

src/shared/db/schema/irc.ts (1)

12-13: LGTM — generated select/insert schemas are exported for reuse.
Please double-check that drizzle-zod v0.8.3’s createSelectSchema / createInsertSchema signatures align with this usage.

Also applies to: 54-56

src/shared/schemas/utils.ts (1)

11-40: LGTM — shared schema helpers are clear and reusable.
Please confirm the union + transform in optionalNonEmptyStringSchema behaves as intended in Zod v4.

package.json (1)

97-97: drizzle-zod 0.8.3 is compatible with the current versions. The package supports zod ^3.25.0 || ^4.0.0 and drizzle-orm >=0.36.0, and your versions (zod 4.3.5 and drizzle-orm 1.0.0-beta.8-734e789) satisfy these requirements.

src/shared/schemas/integrations/index.ts (1)

1-7: LGTM!

The barrel file provides a clean single entry point for integration schemas, consistent with the project's established patterns for centralized modules like @/auth and @/db. This aligns with the PR's architectural decision to centralize Zod schemas.

src/shared/schemas/index.ts (1)

1-7: LGTM!

The top-level schema barrel provides unified access to all Zod schemas, supporting the "validate all inputs with Zod schemas" guideline by making schemas easily accessible throughout the codebase.

src/features/integrations/lib/xmpp/types.ts (1)

7-51: LGTM!

The refactor to z.infer<typeof ...Schema> creates a single source of truth where Zod schemas define both runtime validation and compile-time types. This eliminates the risk of type/schema drift and is idiomatic Zod usage.

src/features/integrations/lib/irc/implementation.ts (1)

53-60: Good validation pattern with descriptive errors.

The validation extracts and surfaces the specific Zod issue message, providing clear feedback to callers. This is the preferred pattern for Zod validation error handling.

src/features/integrations/lib/irc/types.ts (1)

7-60: LGTM!

The refactor correctly uses z.infer<typeof ...Schema> for input/output types while appropriately keeping Atheme-specific runtime types (AthemeFault, AthemeFaultCode) and result types (CreateIrcAccountResult) as explicit interfaces. This maintains a clear separation between schema-validated types and runtime-specific structures.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Address PR #37 review comments from Amazon Q Developer and Sourcery AI:

- Add full validation to `nick` field in UpdateIrcAccountRequestSchema
  - Apply same trim, min, max, and refine rules as CreateIrcAccountRequestSchema
  - Prevents invalid nicks from passing schema validation

- Add full validation to `username` field in UpdateXmppAccountRequestSchema
  - Apply same trim, min, and refine rules as CreateXmppAccountRequestSchema
  - Prevents invalid usernames from passing schema validation

Both update schemas now enforce the same validation rules as their
corresponding create schemas, ensuring data integrity at the schema level
even though the implementation may reject certain updates.

Fixes: #37 (comment)
Fixes: #37 (comment)
- identified by Cubic: Update IRC/XMPP schemas now use .partial() to inherit strict validation from create schemas.
- identified by Cubic: Clarified metadataSchema documentation to reflect its object-only constraint.

These changes ensure robust validation for update requests and maintain consistency between create/update flows.
- Address model review feedback (high priority):
  - Replace unsafe type assertions for metadata with safe metadataSchema.parse().
  - Update metadataSchema to convert null to undefined for IntegrationAccount compatibility.
- Address model review feedback (medium priority):
  - Move global Biome performance rule disables to targeted overrides.
  - Fix linter errors in src/app/metadata.ts and biome.jsonc itself.
  - Update ZOD.md examples to show safe parsing pattern.

All safety and configuration issues identified in the latest review are now resolved.
All checks (type-check, linter) pass.
Copy link

@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.

1 issue found across 7 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/shared/schemas/integrations/irc.ts">

<violation number="1" location="src/shared/schemas/integrations/irc.ts:75">
P2: Avoid calling `.parse()` inside `.transform()`. If parsing fails, the error won't have proper path context and bypasses Zod's error handling. Instead, override the `metadata` field using `.extend()` or `.merge()` with the schema directly.</violation>
</file>

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

Copy link

@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

🤖 Fix all issues with AI agents
In `@biome.jsonc`:
- Around line 17-33: Remove "src/shared/types/api.ts" from the biome.jsonc
includes list so it is no longer exempted from the noBarrelFile rule; locate the
includes array (the entries containing "src/shared/schemas/index.ts",
"src/features/integrations/api/index.ts", etc.) and delete the
"src/shared/types/api.ts" entry, leaving the other seven entries intact (note
that the actual types barrel is handled via an inline biome-ignore in
src/shared/types/index.ts).
🧹 Nitpick comments (1)
biome.jsonc (1)

10-13: Narrow the global noNamespaceImport disable or drop the rule.

Disabling it for all **/*.ts and **/*.tsx (lines 36–45) makes the rule ineffective for TypeScript files, which directly conflicts with the guideline to prefer specific imports over namespace imports in TypeScript. Unlike the narrowly scoped noBarrelFile exceptions, this override is too broad. Either limit it to specific files that legitimately require namespace imports, or remove the rule to avoid a false signal of enforcement.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aec284c and e0b22d8.

📒 Files selected for processing (7)
  • biome.jsonc
  • docs/ZOD.md
  • src/features/integrations/lib/irc/types.ts
  • src/features/integrations/lib/xmpp/types.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/shared/schemas/utils.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/shared/schemas/utils.ts
  • src/features/integrations/lib/irc/types.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

**/*.{js,jsx,ts,tsx}: Use Sentry.captureException(error) to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected
Use Sentry.startSpan() function to create spans for meaningful actions within applications like button clicks, API calls, and function calls

Files:

  • src/features/integrations/lib/xmpp/types.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

When creating custom spans for API calls with Sentry.startSpan(), ensure the name and op properties are meaningful (e.g., op: "http.client" with descriptive names like GET /api/users/${userId}), and attach attributes based on relevant request information and metrics

Files:

  • src/features/integrations/lib/xmpp/types.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

**/*.{js,ts,jsx,tsx}: Import Sentry using import * as Sentry from "@sentry/nextjs" when using logs in NextJS projects
Reference the Sentry logger using const { logger } = Sentry when using logging functionality
Use logger.fmt as a template literal function to bring variables into structured logs, providing better log formatting and variable interpolation

Files:

  • src/features/integrations/lib/xmpp/types.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
**/*.{css,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/tailwind-v4.mdc)

Use container query support with @container, @sm:, @md: for container-based breakpoints and @max-md: for max-width queries

Files:

  • src/features/integrations/lib/xmpp/types.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
**/*.{ts,tsx,js,jsx,html}

📄 CodeRabbit inference engine (.cursor/rules/tailwind-v4.mdc)

**/*.{ts,tsx,js,jsx,html}: Use 3D transform utilities: transform-3d, rotate-x-*, rotate-y-*, rotate-z-*, scale-z-*, translate-z-*, perspective-*, and perspective-origin-*
Use linear gradient angles with bg-linear-45 syntax and gradient interpolation like bg-linear-to-r/oklch or bg-linear-to-r/srgb
Use conic and radial gradients with bg-conic and bg-radial-[at_25%_25%] utilities
Use inset-shadow-* and inset-ring-* utilities instead of deprecated shadow opacity utilities
Use field-sizing-content utility for auto-resizing textareas
Use scheme-light and scheme-dark utilities for color-scheme property
Use font-stretch-* utilities for variable font configuration
Chain variants together for composable variants (e.g., group-has-data-potato:opacity-100)
Use starting variant for @starting-style transitions
Use not-* variant for :not() pseudo-class (e.g., not-first:mb-4)
Use inert variant for styling elements with the inert attribute
Use nth-* variants: nth-3:, nth-last-5:, nth-of-type-4:, nth-last-of-type-6: for targeting specific elements
Use in-* variant as a simpler alternative to group-* without adding group class
Use open variant to support :popover-open pseudo-class
Use ** variant for targeting all descendants
Replace deprecated bg-opacity-* utilities with color values using slash notation (e.g., bg-black/50)
Replace deprecated text-opacity-* utilities with color values using slash notation (e.g., text-black/50)
Replace deprecated border-opacity-*, divide-opacity-* and similar opacity utilities with color slash notation
Use shadow-xs instead of shadow-sm and shadow-sm instead of shadow
Use drop-shadow-xs instead of drop-shadow-sm and drop-shadow-sm instead of drop-shadow
Use blur-xs instead of blur-sm and blur-sm instead of blur
Use rounded-xs instead of rounded-sm and rounded-sm instead of rounded
Use outline-hidden instead of outline-none for...

Files:

  • src/features/integrations/lib/xmpp/types.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/tanstack-query.mdc)

**/*.{ts,tsx}: Create QueryClient using getQueryClient() function that automatically handles server/client isolation (new instance per server request, singleton on client)
Always use the centralized query key factory from src/lib/api/query-keys.ts instead of creating keys manually
Include all variables used in queryFn in the query key to ensure proper cache management and query invalidation

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

**/*.{ts,tsx}: Use TypeScript strict mode with explicit types; prefer unknown over any
Use functional components and hooks in React code
Use selective imports over barrel exports for performance
Follow Next.js App Router conventions
Always await promises in async functions
Use semantic HTML and ARIA attributes for accessibility
Import authentication operations from @/auth module using barrel exports
Import database operations from @/db module using barrel exports
Import app configuration from @/config or @/config/app using barrel exports
Import UI components using direct imports from @/components/ui/* (e.g., @/components/ui/button)
Import custom hooks using direct imports from @/hooks/* (e.g., @/hooks/use-permissions)
Centralize major types in src/types/ directory: use @/types/auth, @/types/api, @/types/routes, @/types/email, @/types/common for imports
Import major constants from @/lib/utils/constants.ts: USER_ROLES, PERMISSIONS, HTTP_STATUS, API_ERROR_CODES, QUERY_CACHE, RATE_LIMIT, INTEGRATION_STATUSES, PAGINATION, VALIDATION_PATTERNS, MOBILE_BREAKPOINT, DATE_FORMATS
Use TanStack Query for all server state management and data fetching
Optimize images with next/image component instead of HTML img tags
Validate all input...

Files:

  • src/features/integrations/lib/xmpp/types.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{ts,tsx,js,jsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Use function components over class components
Call hooks at the top level only, never conditionally
Specify all dependencies in hook dependency arrays correctly
Use the key prop for elements in iterables (prefer unique IDs over array indices)
Nest children between opening and closing tags instead of passing as props in React components
Don't define components inside other components
Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, and use semantic elements instead of divs with roles
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Keep functions focused and under reasonable cognitive complexity limits
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Group related code together and separate concerns
Add `...

Files:

  • src/features/integrations/lib/xmpp/types.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Validate all inputs with Zod schemas
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Centralize major types in `src/types/` directory: use `@/types/auth`, `@/types/api`, `@/types/routes`, `@/types/email`, `@/types/common` for imports

Applied to files:

  • src/features/integrations/lib/xmpp/types.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Validate all inputs with Zod schemas

Applied to files:

  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
  • docs/ZOD.md
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/backend/**/*.{ts,tsx,js,jsx} : Mandatory Zod validation at boundaries in backend

Applied to files:

  • src/shared/schemas/integrations/irc.ts
  • docs/ZOD.md
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Avoid barrel files (index files that re-export everything)

Applied to files:

  • biome.jsonc
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use single quotes and no semicolons (enforced by Biome configuration)

Applied to files:

  • biome.jsonc
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Use selective imports over barrel exports for performance

Applied to files:

  • biome.jsonc
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import app configuration from `@/config` or `@/config/app` using barrel exports

Applied to files:

  • biome.jsonc
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Remove empty AI-words ('robust', 'seamless', etc.) (red flag in nuclear mode)

Applied to files:

  • biome.jsonc
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Prefer specific imports over namespace imports

Applied to files:

  • biome.jsonc
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Remove commented-out code (red flag in nuclear mode)

Applied to files:

  • biome.jsonc
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Focus code review attention on business logic correctness, meaningful naming, architecture decisions, edge cases, user experience, and documentation since Biome handles most formatting and common issues automatically

Applied to files:

  • biome.jsonc
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Don't use `.only` or `.skip` in committed code

Applied to files:

  • biome.jsonc
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Remove syntax comments (red flag in nuclear mode)

Applied to files:

  • biome.jsonc
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Remove `console.log`, `debugger`, and `alert` statements from production code

Applied to files:

  • biome.jsonc
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Remove unused imports (nuclear mode)

Applied to files:

  • biome.jsonc
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Keep functions focused and under reasonable cognitive complexity limits

Applied to files:

  • biome.jsonc
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import major constants from `@/lib/utils/constants.ts`: `USER_ROLES`, `PERMISSIONS`, `HTTP_STATUS`, `API_ERROR_CODES`, `QUERY_CACHE`, `RATE_LIMIT`, `INTEGRATION_STATUSES`, `PAGINATION`, `VALIDATION_PATTERNS`, `MOBILE_BREAKPOINT`, `DATE_FORMATS`

Applied to files:

  • biome.jsonc
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/lib/*/keys.ts : Define module environment variables using t3-env `createEnv` with Zod schemas in module-level `keys.ts` files

Applied to files:

  • docs/ZOD.md
🧬 Code graph analysis (1)
src/shared/schemas/integrations/xmpp.ts (4)
src/features/integrations/lib/xmpp/utils.ts (1)
  • isValidXmppUsername (28-41)
src/shared/schemas/utils.ts (1)
  • metadataSchema (25-28)
src/shared/db/schema/xmpp.ts (1)
  • selectXmppAccountSchema (57-57)
src/features/integrations/lib/xmpp/types.ts (5)
  • XmppAccountStatus (12-12)
  • UpdateXmppAccountStatus (10-10)
  • CreateXmppAccountRequest (8-8)
  • UpdateXmppAccountRequest (9-9)
  • XmppAccount (11-11)
🪛 markdownlint-cli2 (0.20.0)
docs/ZOD.md

[warning] 28-28: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 130-130: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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: Sourcery review
  • GitHub Check: Seer Code Review
  • GitHub Check: cubic · AI code reviewer
🔇 Additional comments (5)
src/shared/schemas/integrations/xmpp.ts (2)

25-52: Good reuse of username validation for create/update flows.


58-66: Metadata parsing in the account transform is solid.

src/features/integrations/lib/xmpp/types.ts (1)

7-13: Type re-exports from shared schemas keep a single source of truth.

src/shared/schemas/integrations/irc.ts (2)

32-61: Nice validation parity between create and update schemas.


67-76: Metadata normalization in the response schema looks good.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

…RC/XMPP Zod schemas by directly defining metadata.
…us form templates and update integration schemas and documentation."
…specific schemas

Enhance the request body validation by utilizing integration-specific
schemas when available. This change allows for more precise validation
of incoming data, ensuring that only valid data is processed. If an
integration does not provide a schema, a fallback schema is used to
maintain backward compatibility. This refactor also prepares for future
enhancements by adding a TODO for returning detailed field errors once
the frontend supports it.
…nd update functions

Add generic types TCreateInput and TUpdateInput to the
createIntegrationAccount and updateIntegrationAccount functions,
respectively. This change allows for more flexibility and type
safety when specifying the input structure for these functions,
enabling better code reuse and reducing potential errors when
dealing with different input shapes.
…t hooks

Introduce generic type parameters `TCreateInput` and `TUpdateInput` to the `useCreateIntegrationAccount` and `useUpdateIntegrationAccount` hooks, respectively. This change allows for more flexibility and type safety by enabling the specification of custom input types when creating or updating integration accounts. The default type remains `Record<string, unknown>`, ensuring backward compatibility.
Introduce optional `createAccountSchema` and `updateAccountSchema`
properties to `IntegrationBaseOptions` and `IntegrationBase` class.
These properties utilize `zod` for schema validation, allowing
integration implementations to define and enforce input validation
rules for account creation and updates. This change enhances the
robustness and reliability of integrations by ensuring data integrity
throughout the lifecycle of integration operations.
Introduce `createAccountSchema` and `updateAccountSchema` properties
to the `Integration` interface, allowing for the definition of Zod
schemas for account creation and update inputs. This enhances the
type safety and validation capabilities of the integration by
leveraging Zod's schema validation. The addition of these properties
enables more robust input validation, reducing potential runtime
errors and improving the overall reliability of the integration
process.
Introduce `createAccountSchema` and `updateAccountSchema` to the IRC
integration configuration. This change enhances the robustness of the
IRC integration by ensuring that account creation and updates adhere to
defined schemas, reducing the likelihood of errors due to invalid data.
Import CreateXmppAccountRequestSchema and include it in the XmppIntegration
class. This change allows the integration to handle account creation requests
by validating them against the new schema, enhancing the functionality and
robustness of the XMPP integration.
… safety

The IrcNickSchema now uses the brandedString utility to create a branded type, enhancing type safety by associating a specific type with the IRC nick. This change improves the robustness of the code by ensuring that only valid IRC nick strings are used where the IrcNick type is expected.
…e type safety

The XmppUsernameSchema now utilizes the brandedString utility to provide
a more robust type definition, enhancing type safety and ensuring that
the schema is correctly identified as an XMPP username. This change
improves code maintainability and reduces potential errors related to
type mismatches.
…d string schemas

Introduce a new utility function, brandedString, to facilitate the creation of branded string schemas using Zod. This addition enhances type safety by allowing developers to define and enforce specific string types throughout the application, reducing potential errors and improving code maintainability.
Copy link

@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.

14 issues found across 27 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name=".cursor/skills/react-hook-form-zod/rules/react-hook-form-zod.md">

<violation number="1" location=".cursor/skills/react-hook-form-zod/rules/react-hook-form-zod.md:77">
P2: The example uses `await` inside a non-async `onSubmit` function. Mark the function as async so the snippet is valid when copied.</violation>
</file>

<file name=".cursor/skills/react-hook-form-zod/templates/multi-step-form.tsx">

<violation number="1" location=".cursor/skills/react-hook-form-zod/templates/multi-step-form.tsx:50">
P1: Password confirmation validation is lost during schema merge. Zod's `.merge()` does not preserve `.refine()` validations. Users can submit mismatched passwords.

Add the refinement to `fullFormSchema` after merging, or extract the base object schema from `step3Schema` before applying the refinement.</violation>
</file>

<file name=".cursor/skills/react-hook-form-zod/templates/async-validation.tsx">

<violation number="1" location=".cursor/skills/react-hook-form-zod/templates/async-validation.tsx:24">
P2: Missing error handling in async validation. If the fetch fails or returns invalid JSON, validation will throw. Consider wrapping in try-catch and returning `true` (or `false`) on error to allow form submission to proceed (or fail gracefully).</violation>

<violation number="2" location=".cursor/skills/react-hook-form-zod/templates/async-validation.tsx:163">
P1: Bug: Shared `timeoutRef` between username and email validation effects causes race condition. If user types in both fields within 500ms, one field's debounce timeout gets cancelled by the other. Use separate timeout refs for each field (e.g., `usernameTimeoutRef` and `emailTimeoutRef`).</violation>
</file>

<file name=".cursor/skills/react-hook-form-zod/SKILL.md">

<violation number="1" location=".cursor/skills/react-hook-form-zod/SKILL.md:21">
P3: Quick Start installs react-hook-form@7.70.0, which conflicts with the documented latest version (7.71.1). This can mislead users into installing an outdated version.</violation>
</file>

<file name="src/app/api/integrations/[integration]/accounts/route.ts">

<violation number="1" location="src/app/api/integrations/[integration]/accounts/route.ts:79">
P1: Missing error handling for malformed JSON. The `request.json()` call can throw a `SyntaxError` if the body is not valid JSON. Unlike the original code, this is no longer caught, causing a 500 "Internal server error" instead of the expected 400 "Invalid JSON body" response.</violation>
</file>

<file name=".cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx">

<violation number="1" location=".cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx:91">
P2: The `useEffect` depends on `onClose`, but the caller passes an inline function which creates a new reference on every render. This resets the 5-second timer on each parent re-render, potentially preventing auto-close. Either wrap the callback in `useCallback` in the parent, or use a ref to store `onClose` in ErrorToast.</violation>

<violation number="2" location=".cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx:165">
P2: The `aria-describedby` references `'username-error'` but the `FormError` component doesn't render an element with that ID. Screen readers won't be able to associate the error message with the input. Either remove `aria-describedby` (since FormError already has `role="alert"`) or add an `id` prop to FormError.</violation>
</file>

<file name=".cursor/skills/react-hook-form-zod/templates/advanced-form.tsx">

<violation number="1" location=".cursor/skills/react-hook-form-zod/templates/advanced-form.tsx:109">
P2: Default value `['']` will fail Zod validation since the schema requires each skill to be at least 1 character (`.min(1, 'Skill cannot be empty')`). Either initialize with an empty array `[]` or remove the `.min(1)` constraint from individual skills.</violation>
</file>

<file name=".cursor/skills/react-hook-form-zod/templates/basic-form.tsx">

<violation number="1" location=".cursor/skills/react-hook-form-zod/templates/basic-form.tsx:52">
P2: Avoid logging credential payloads; this leaks passwords to the browser console. Guard the log to non-production or remove it entirely.</violation>

<violation number="2" location=".cursor/skills/react-hook-form-zod/templates/basic-form.tsx:195">
P2: Avoid logging signup payloads containing passwords. Guard the log to non-production or remove it entirely.</violation>
</file>

<file name=".cursor/skills/react-hook-form-zod/templates/dynamic-fields.tsx">

<violation number="1" location=".cursor/skills/react-hook-form-zod/templates/dynamic-fields.tsx:20">
P2: The phone field is marked optional, but the schema rejects the default empty string. This causes validation errors even when users leave the optional phone field blank. Allow empty strings (or preprocess them to undefined) to align with the default value and optional UI.</violation>

<violation number="2" location=".cursor/skills/react-hook-form-zod/templates/dynamic-fields.tsx:166">
P3: The "Add at Top" button bypasses the 10-item cap and can insert more contacts than the schema allows. Mirror the max-length guard used by the "Add Contact" button to prevent invalid states.</violation>
</file>

<file name=".cursor/skills/react-hook-form-zod/templates/server-validation.ts">

<violation number="1" location=".cursor/skills/react-hook-form-zod/templates/server-validation.ts:145">
P1: The Hono response returns the full `user` object from `createUser`, which includes the plaintext password. Return only safe fields to avoid exposing credentials.</violation>
</file>

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

Copy link

@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: 16

🤖 Fix all issues with AI agents
In @.cursor/skills/designing-zod-schemas/SKILL.md:
- Around line 95-99: The three referenced pattern files
(references/primitive-patterns.md, references/object-patterns.md,
references/testing-patterns.md) are missing; either add those markdown files
under the references folder containing the described content (Primitive
Patterns: strings, numbers, enums, branded types; Object Patterns: objects,
discriminated unions, arrays, transforms, refinements; Testing Patterns: test
data builders, schema validation tests) and link them from SKILL.md, or remove
the three bullet references in SKILL.md (the list items mentioning those
filenames) so the doc no longer points to nonexistent files—update whichever
approach you choose and ensure the filenames in SKILL.md match the created files
exactly.

In @.cursor/skills/react-hook-form-zod/scripts/check-versions.sh:
- Around line 29-42: Replace the fragile tail/head JSON slicing with a
Node-based JSON parse that reliably extracts the last 5 versions from the npm
view output; specifically, for each occurrence of the pipeline starting with
"npm view <pkg> versions --json | tail -7 | head -6" (the lines for
react-hook-form, zod, and `@hookform/resolvers`) run the npm view JSON through a
small Node one-liner that parses the JSON and prints the last 5 entries (e.g.,
JSON.parse(...).slice(-5).forEach(...)), so the script prints the actual last
five versions for each package.

In @.cursor/skills/react-hook-form-zod/SKILL.md:
- Around line 14-22: Update the npm install line so the react-hook-form version
matches the stated "Latest Versions" header: change the package spec in the
install command (the line containing "npm install react-hook-form@7.70.0
zod@4.3.5 `@hookform/resolvers`@5.2.2") to use react-hook-form@7.71.1 so it aligns
with the referenced latest version.

In @.cursor/skills/react-hook-form-zod/templates/advanced-form.tsx:
- Around line 31-32: The phone schema currently uses phone:
z.string().regex(/^\+?[1-9]\d{1,14}$/, 'Invalid phone number').optional(), which
treats an untouched input ('') as a string and fails the regex; wrap the phone
schema in a preprocess that converts empty-string inputs to undefined before
validation (e.g. use z.preprocess(value => value === '' ? undefined : value,
z.string().regex(...).optional())) so the optional field accepts blank
submissions; update the phone field definition accordingly.
- Around line 47-49: Replace the deprecated errorMap option on the experience
enum with the Zod v4 unified error API: update the experience field declaration
(the z.enum([...], { ... }) call) to use the error property instead of errorMap
and return the same message object (e.g. error: (issue) => ({ message: 'Please
select experience level' })), so the schema uses the new Zod v4 signature.

In @.cursor/skills/react-hook-form-zod/templates/async-validation.tsx:
- Line 163: The shared timeoutRef used for debouncing validations causes
cross-field interference; replace it with separate refs (e.g.,
usernameTimeoutRef and emailTimeoutRef typed NodeJS.Timeout | null) and update
both the username validation effect and the email validation effect (and any
cleanup logic in the range referenced) to use their corresponding ref when
setting and clearing timeouts so each field manages its own debounce timer
independently.

In @.cursor/skills/react-hook-form-zod/templates/basic-form.tsx:
- Around line 50-73: The onSubmit handler logs the entire LoginFormData
(including password) which can leak sensitive data; update the onSubmit function
to remove the console.log('Form data:', data) and instead log only non-sensitive
identifiers or status messages (e.g., log attempted username/email from
data.username or data.email, or a generic "submitting login" message), keep the
existing success/failure logs (console.log('Login successful:', result) can
remain) and ensure reset() is still called on success; reference the onSubmit
function and the LoginFormData type to locate and change the logging behavior.

In @.cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx:
- Around line 30-43: The FormError component renders inline error text but does
not accept or render an id, so inputs using aria-describedby (e.g.,
"username-error") point to non-existent elements; update FormError to accept an
optional id prop (e.g., id?: string) and render it on the outer div, then ensure
all form input components set aria-describedby to the matching ids (like
`${fieldName}-error`) wherever errors are rendered; search for usages of
FormError and input fields in this template and add consistent id wiring so
screen readers can associate inputs with their error messages.

In @.cursor/skills/react-hook-form-zod/templates/multi-step-form.tsx:
- Around line 44-50: The merge order is causing a Zod error because step3Schema
contains a .refine(), so instead of merging schemas that already have
refinements, combine the raw object shapes first (merge step1Schema,
step2Schema, step3's base object/schema without refine) into fullFormSchema and
then apply the password .refine() on the resulting fullFormSchema (or move the
password check into a separate refinement variable and apply it after merging);
update references to step1Schema, step2Schema, step3Schema, fullFormSchema and
the refine call accordingly.

In @.cursor/skills/react-hook-form-zod/templates/server-validation.ts:
- Around line 141-146: The handler is returning the full user object from
createUser (which includes password); update the response to project a safe
payload (e.g., pick id, name, email, createdAt, etc.) instead of returning the
raw user. Locate the response blocks that call createUser (the one that does
res.json({ success: true, user }) and the other similar responses) and replace
user with a sanitized object (omit password and any sensitive fields) before
sending; keep the internal createUser return unchanged but always map its result
to a safeUser projection in the route handlers.
- Around line 120-127: The Express example is missing JSON body parsing so
req.body will be undefined when userRegistrationSchema.parse is called; add the
JSON middleware by registering express.json() on the app (call
app.use(express.json()) before the app.post route) so that requests have
req.body populated for userRegistrationSchema.parse in the
app.post('/api/register', ...) handler.
- Around line 120-171: The file declares two separate constants named "app" (the
Express instance and the Hono instance) causing a redeclaration/syntax error;
rename one or both (for example expressApp for the Express instance and honoApp
for the Hono instance) and update all usages (e.g., change
app.post('/api/register', ...) for the Express block to expressApp.post(...) and
the Hono handler to honoApp.post(...)), keeping the same route handlers,
middleware references (userRegistrationSchema, zValidator), and error handling
logic intact.

In @.cursor/skills/react-hook-form-zod/templates/shadcn-form.tsx:
- Around line 38-52: The notifications field in profileFormSchema currently
chains .default(false).optional(), which prevents Zod from applying the default;
update the notifications definition inside profileFormSchema to either
.optional().default(false) or simply .default(false) (e.g., change the
notifications line to use .default(false) or .optional().default(false)) so the
schema returns a defined boolean when missing.

In @.cursor/skills/zod/AGENTS.md:
- Around line 1-97: AGENTS.md lists many support files that don't exist (e.g.,
references/_sections.md, assets/templates/_template.md, metadata.json) causing
broken references; either add the missing files with the referenced content or
remove/update the "Source Files" section and all inline references to
non-existent paths. Locate the "Source Files" table and any links to
references/*.md, assets/*, and metadata.json in AGENTS.md and choose one fix:
(A) create the missing files matching the referenced names and minimal content
placeholders (references/_sections.md plus each referenced references/*.md,
assets/templates/_template.md, metadata.json) and ensure links resolve, or (B)
remove or replace all links to non-existent files and rewrite the "Source Files"
section to only list existing artifacts (AGENTS.md and SKILL.md) and remove dead
references; apply the chosen change consistently across the whole document
(headings, table of contents, and references list).

In `@src/app/api/integrations/`[integration]/accounts/route.ts:
- Around line 79-80: Wrap the call to request.json() (where rawBody and body are
set) in a try/catch so JSON parse failures are handled explicitly; catch
SyntaxError (or any parsing error) and return or throw a 400-level API error
that handleAPIError can convert to a user-friendly 400 response (e.g., throw new
Error with status 400 or return a NextResponse with status 400 and a message
like "Invalid JSON body"), otherwise assign parsed value to rawBody/body as
before.

In `@src/features/integrations/hooks/use-integration.ts`:
- Around line 54-59: There are two identical JSDoc blocks above the
useCreateIntegrationAccount hook; remove the redundant comment so only one JSDoc
remains directly above the useCreateIntegrationAccount declaration. Locate the
duplicate comment blocks surrounding the useCreateIntegrationAccount function
and delete the extra block (keep the one that best documents the hook) to avoid
repeated documentation.
🧹 Nitpick comments (11)
.cursor/skills/react-hook-form-zod/templates/dynamic-fields.tsx (3)

45-48: Unused update destructured from useFieldArray.

The update function is destructured but never used in this component.

♻️ Remove unused variable
-  const { fields, append, remove, insert, update } = useFieldArray({
+  const { fields, append, remove, insert } = useFieldArray({
     control,
     name: 'contacts',
   })

164-170: Missing disabled check on "Add at Top" button.

The "Add Contact" button correctly disables when fields.length >= 10, but the "Add at Top" button lacks this check. Both buttons can add contacts, so they should enforce the same constraint for consistency.

♻️ Add disabled check for consistency
         <button
           type="button"
           onClick={() => insert(0, { name: '', email: '', phone: '', isPrimary: false })}
+          disabled={fields.length >= 10}
           className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
         >
           Add at Top
         </button>

252-291: Missing accessibility labels and error displays for skill fields.

As a template demonstrating best practices, this form should include:

  1. Labels for all form fields — The skill name input, level select, and years input lack associated <label> elements (only placeholder text for the input). Screen readers won't announce these fields properly.
  2. Error displays for all validated fieldslevel and yearsOfExperience have Zod validation but no corresponding error message rendering.

Compare with DynamicContactList which correctly uses labels (lines 85-86, 102-103, etc.).

♻️ Add labels and error displays
           <div key={field.id} className="border rounded p-3 flex gap-3 items-start">
             <div className="flex-1 space-y-2">
+              <label htmlFor={`skills.${index}.name`} className="sr-only">Skill name</label>
               <input
+                id={`skills.${index}.name`}
                 {...register(`skills.${index}.name` as const)}
                 placeholder="Skill name"
                 className="w-full px-2 py-1 border rounded text-sm"
               />
               {errors.skills?.[index]?.name && (
                 <span className="text-xs text-red-600">{errors.skills[index]?.name?.message}</span>
               )}

               <div className="grid grid-cols-2 gap-2">
+                <div>
+                  <label htmlFor={`skills.${index}.level`} className="sr-only">Skill level</label>
                   <select
+                    id={`skills.${index}.level`}
                     {...register(`skills.${index}.level` as const)}
                     className="px-2 py-1 border rounded text-sm"
                   >
                     <option value="beginner">Beginner</option>
                     <option value="intermediate">Intermediate</option>
                     <option value="advanced">Advanced</option>
                     <option value="expert">Expert</option>
                   </select>
+                  {errors.skills?.[index]?.level && (
+                    <span className="text-xs text-red-600">{errors.skills[index]?.level?.message}</span>
+                  )}
+                </div>

+                <div>
+                  <label htmlFor={`skills.${index}.yearsOfExperience`} className="sr-only">Years of experience</label>
                   <input
+                    id={`skills.${index}.yearsOfExperience`}
                     type="number"
                     {...register(`skills.${index}.yearsOfExperience` as const, { valueAsNumber: true })}
                     placeholder="Years"
                     className="px-2 py-1 border rounded text-sm"
                   />
+                  {errors.skills?.[index]?.yearsOfExperience && (
+                    <span className="text-xs text-red-600">{errors.skills[index]?.yearsOfExperience?.message}</span>
+                  )}
+                </div>
               </div>
             </div>
.cursor/skills/react-hook-form-zod/templates/basic-form.tsx (1)

199-274: Accessibility attributes missing in signup form fields.

The BasicSignupForm lacks the accessibility attributes present in BasicLoginForm:

  • Missing aria-invalid on inputs
  • Missing aria-describedby linking inputs to error messages
  • Error spans missing id attributes

Since this is a template developers will copy, both forms should demonstrate consistent best practices.

♿ Example fix for the name field (apply same pattern to other fields)
         <input
           id="name"
           {...register('name')}
+          aria-invalid={errors.name ? 'true' : 'false'}
+          aria-describedby={errors.name ? 'name-error' : undefined}
           className="w-full px-3 py-2 border rounded-md"
           placeholder="John Doe"
         />
         {errors.name && (
-          <span role="alert" className="text-sm text-red-600 mt-1 block">
+          <span id="name-error" role="alert" className="text-sm text-red-600 mt-1 block">
             {errors.name.message}
           </span>
         )}
.cursor/skills/designing-zod-schemas/SKILL.md (1)

41-41: Address markdown formatting issues.

The markdownlint tool has flagged several formatting inconsistencies:

  1. Tables (Lines 41, 117, 125): Add spaces around pipe characters for consistent "compact" style
  2. Code fences (Lines 103, 135): Add language specifiers (e.g., text or bash)
  3. Bare URL (Line 143): Format as markdown link: [Zod documentation](https://zod.dev)
📝 Proposed formatting fixes

For table formatting (example from Line 41):

-|------|---------|---------|
+| ------ | --------- | --------- |

For code fences (Line 103):

-```
+```text

For bare URL (Line 143):

-- Zod documentation: https://zod.dev
+- [Zod documentation](https://zod.dev)

Also applies to: 103-103, 117-117, 125-125, 135-135, 143-143

src/shared/schemas/utils.ts (1)

17-28: Remove duplicate JSDoc comment.

There are two consecutive JSDoc comments for metadataSchema (lines 17-20 and 21-24). Remove the first one.

📝 Proposed fix
-/**
- * Metadata schema for JSONB fields
- * Safe schema for parsing metadata objects, allowing null or undefined
- */
 /**
  * Metadata schema for JSONB fields
  * Safe schema for parsing metadata objects, converting null to undefined for interface compatibility
  */
 export const metadataSchema = z.preprocess(
.cursor/skills/react-hook-form-zod/templates/multi-step-form.tsx (1)

176-186: Consider adding explicit label-input associations for accessibility.

Form inputs have visible labels but lack htmlFor/id associations. While inputs are implicitly associated by nesting, explicit associations improve screen reader compatibility.

♿ Example improvement
 <div>
-  <label className="block text-sm font-medium mb-1">First Name *</label>
+  <label htmlFor="firstName" className="block text-sm font-medium mb-1">First Name *</label>
   <input
+    id="firstName"
     {...register('firstName')}
     className="w-full px-3 py-2 border rounded-md"
   />
src/features/integrations/api/integrations.ts (1)

93-116: Consider adding client-side schema validation option.

While server-side validation is the primary boundary (per coding guidelines), the generic input types could optionally accept a schema for client-side pre-validation to catch errors before network calls.

This is a nice-to-have for future consideration, not blocking.

src/features/integrations/lib/xmpp/implementation.ts (1)

243-246: Consider including validation error details in the error message.

The current implementation discards specific Zod validation errors, returning only "Invalid update request". Including the first issue message would aid debugging.

♻️ Suggested improvement
     const parsed = UpdateXmppAccountRequestSchema.safeParse(input);
     if (!parsed.success) {
-      throw new Error("Invalid update request");
+      const errorMessage = parsed.error.issues[0]?.message ?? "Invalid update request";
+      throw new Error(errorMessage);
     }
.cursor/skills/react-hook-form-zod/templates/async-validation.tsx (1)

208-211: Replace any with unknown for error type.

Per coding guidelines, prefer unknown over any when the type is genuinely unknown.

♻️ Suggested fix
-      } catch (error: any) {
-        if (error.name !== 'AbortError') {
+      } catch (error: unknown) {
+        if (error instanceof Error && error.name !== 'AbortError') {
           console.error('Username check error:', error)
         }
.cursor/skills/react-hook-form-zod/templates/shadcn-form.tsx (1)

197-223: Align settingsFormSchema.language with the actual fields.
language is required in the schema but the form never exposes a control for it, so submissions always carry the default and the user can’t change it. Either add a field or remove it from the schema/defaults.

🧹 Proposed alignment (remove unused field)
 const settingsFormSchema = z.object({
   name: z.string().min(1, 'Name is required'),
-  language: z.string(),
   theme: z.enum(['light', 'dark', 'system']),
   emailPreferences: z.object({
     marketing: z.boolean().default(false),
     updates: z.boolean().default(true),
     security: z.boolean().default(true),
   }),
 })
@@
     defaultValues: {
       name: '',
-      language: 'en',
       theme: 'system',
       emailPreferences: {
         marketing: false,
         updates: true,
         security: true,
       },
     },
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f9acba and f0bf1c3.

📒 Files selected for processing (27)
  • .cursor/skills/designing-zod-schemas/SKILL.md
  • .cursor/skills/react-hook-form-zod/.claude-plugin/plugin.json
  • .cursor/skills/react-hook-form-zod/SKILL.md
  • .cursor/skills/react-hook-form-zod/rules/react-hook-form-zod.md
  • .cursor/skills/react-hook-form-zod/scripts/check-versions.sh
  • .cursor/skills/react-hook-form-zod/templates/advanced-form.tsx
  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
  • .cursor/skills/react-hook-form-zod/templates/basic-form.tsx
  • .cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx
  • .cursor/skills/react-hook-form-zod/templates/dynamic-fields.tsx
  • .cursor/skills/react-hook-form-zod/templates/multi-step-form.tsx
  • .cursor/skills/react-hook-form-zod/templates/package.json
  • .cursor/skills/react-hook-form-zod/templates/server-validation.ts
  • .cursor/skills/react-hook-form-zod/templates/shadcn-form.tsx
  • .cursor/skills/zod/AGENTS.md
  • .cursor/skills/zod/SKILL.md
  • docs/ZOD.md
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/api/integrations.ts
  • src/features/integrations/hooks/use-integration.ts
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/integrations/irc.ts
  • src/shared/schemas/integrations/xmpp.ts
  • src/shared/schemas/utils.ts
✅ Files skipped from review due to trivial changes (2)
  • .cursor/skills/zod/SKILL.md
  • .cursor/skills/react-hook-form-zod/.claude-plugin/plugin.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/shared/schemas/integrations/xmpp.ts
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

**/*.{js,jsx,ts,tsx}: Use Sentry.captureException(error) to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected
Use Sentry.startSpan() function to create spans for meaningful actions within applications like button clicks, API calls, and function calls

Files:

  • src/features/integrations/lib/core/types.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/schemas/utils.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/api/integrations.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/hooks/use-integration.ts
**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

When creating custom spans for API calls with Sentry.startSpan(), ensure the name and op properties are meaningful (e.g., op: "http.client" with descriptive names like GET /api/users/${userId}), and attach attributes based on relevant request information and metrics

Files:

  • src/features/integrations/lib/core/types.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/schemas/utils.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/api/integrations.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/hooks/use-integration.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

**/*.{js,ts,jsx,tsx}: Import Sentry using import * as Sentry from "@sentry/nextjs" when using logs in NextJS projects
Reference the Sentry logger using const { logger } = Sentry when using logging functionality
Use logger.fmt as a template literal function to bring variables into structured logs, providing better log formatting and variable interpolation

Files:

  • src/features/integrations/lib/core/types.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/schemas/utils.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/api/integrations.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/hooks/use-integration.ts
**/*.{css,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/tailwind-v4.mdc)

Use container query support with @container, @sm:, @md: for container-based breakpoints and @max-md: for max-width queries

Files:

  • src/features/integrations/lib/core/types.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/schemas/utils.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/api/integrations.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/hooks/use-integration.ts
**/*.{ts,tsx,js,jsx,html}

📄 CodeRabbit inference engine (.cursor/rules/tailwind-v4.mdc)

**/*.{ts,tsx,js,jsx,html}: Use 3D transform utilities: transform-3d, rotate-x-*, rotate-y-*, rotate-z-*, scale-z-*, translate-z-*, perspective-*, and perspective-origin-*
Use linear gradient angles with bg-linear-45 syntax and gradient interpolation like bg-linear-to-r/oklch or bg-linear-to-r/srgb
Use conic and radial gradients with bg-conic and bg-radial-[at_25%_25%] utilities
Use inset-shadow-* and inset-ring-* utilities instead of deprecated shadow opacity utilities
Use field-sizing-content utility for auto-resizing textareas
Use scheme-light and scheme-dark utilities for color-scheme property
Use font-stretch-* utilities for variable font configuration
Chain variants together for composable variants (e.g., group-has-data-potato:opacity-100)
Use starting variant for @starting-style transitions
Use not-* variant for :not() pseudo-class (e.g., not-first:mb-4)
Use inert variant for styling elements with the inert attribute
Use nth-* variants: nth-3:, nth-last-5:, nth-of-type-4:, nth-last-of-type-6: for targeting specific elements
Use in-* variant as a simpler alternative to group-* without adding group class
Use open variant to support :popover-open pseudo-class
Use ** variant for targeting all descendants
Replace deprecated bg-opacity-* utilities with color values using slash notation (e.g., bg-black/50)
Replace deprecated text-opacity-* utilities with color values using slash notation (e.g., text-black/50)
Replace deprecated border-opacity-*, divide-opacity-* and similar opacity utilities with color slash notation
Use shadow-xs instead of shadow-sm and shadow-sm instead of shadow
Use drop-shadow-xs instead of drop-shadow-sm and drop-shadow-sm instead of drop-shadow
Use blur-xs instead of blur-sm and blur-sm instead of blur
Use rounded-xs instead of rounded-sm and rounded-sm instead of rounded
Use outline-hidden instead of outline-none for...

Files:

  • src/features/integrations/lib/core/types.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/schemas/utils.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/api/integrations.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/hooks/use-integration.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/tanstack-query.mdc)

**/*.{ts,tsx}: Create QueryClient using getQueryClient() function that automatically handles server/client isolation (new instance per server request, singleton on client)
Always use the centralized query key factory from src/lib/api/query-keys.ts instead of creating keys manually
Include all variables used in queryFn in the query key to ensure proper cache management and query invalidation

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

**/*.{ts,tsx}: Use TypeScript strict mode with explicit types; prefer unknown over any
Use functional components and hooks in React code
Use selective imports over barrel exports for performance
Follow Next.js App Router conventions
Always await promises in async functions
Use semantic HTML and ARIA attributes for accessibility
Import authentication operations from @/auth module using barrel exports
Import database operations from @/db module using barrel exports
Import app configuration from @/config or @/config/app using barrel exports
Import UI components using direct imports from @/components/ui/* (e.g., @/components/ui/button)
Import custom hooks using direct imports from @/hooks/* (e.g., @/hooks/use-permissions)
Centralize major types in src/types/ directory: use @/types/auth, @/types/api, @/types/routes, @/types/email, @/types/common for imports
Import major constants from @/lib/utils/constants.ts: USER_ROLES, PERMISSIONS, HTTP_STATUS, API_ERROR_CODES, QUERY_CACHE, RATE_LIMIT, INTEGRATION_STATUSES, PAGINATION, VALIDATION_PATTERNS, MOBILE_BREAKPOINT, DATE_FORMATS
Use TanStack Query for all server state management and data fetching
Optimize images with next/image component instead of HTML img tags
Validate all input...

Files:

  • src/features/integrations/lib/core/types.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/schemas/utils.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/api/integrations.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/hooks/use-integration.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{ts,tsx,js,jsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Use function components over class components
Call hooks at the top level only, never conditionally
Specify all dependencies in hook dependency arrays correctly
Use the key prop for elements in iterables (prefer unique IDs over array indices)
Nest children between opening and closing tags instead of passing as props in React components
Don't define components inside other components
Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, and use semantic elements instead of divs with roles
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Keep functions focused and under reasonable cognitive complexity limits
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Group related code together and separate concerns
Add `...

Files:

  • src/features/integrations/lib/core/types.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/schemas/utils.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/api/integrations.ts
  • src/shared/schemas/integrations/irc.ts
  • src/features/integrations/hooks/use-integration.ts
{src/app/**,src/components/**}/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/tanstack-query.mdc)

{src/app/**,src/components/**}/*.{ts,tsx}: Use useUsers(), useUser(), useSessions(), useAdminStats(), useUpdateUser(), useDeleteUser(), useDeleteSession() hooks from src/hooks/use-admin.ts for standard queries
Use corresponding Suspense hooks (useUsersSuspense(), useUserSuspense(), etc.) from src/hooks/use-admin-suspense.ts when wrapping components in Suspense and Error Boundaries

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
**/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/app/**/*.{ts,tsx}: Implement proper error boundaries in Next.js App Router pages and layouts
Use Suspense for loading states in Next.js App Router components

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Validate all inputs with Zod schemas
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/backend/**/*.{ts,tsx,js,jsx} : Mandatory Zod validation at boundaries in backend
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Validate all inputs with Zod schemas

Applied to files:

  • .cursor/skills/zod/AGENTS.md
  • src/features/integrations/lib/core/types.ts
  • .cursor/skills/react-hook-form-zod/templates/basic-form.tsx
  • .cursor/skills/designing-zod-schemas/SKILL.md
  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
  • src/app/api/integrations/[integration]/accounts/route.ts
  • .cursor/skills/react-hook-form-zod/SKILL.md
  • .cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx
  • .cursor/skills/react-hook-form-zod/templates/multi-step-form.tsx
  • src/shared/schemas/utils.ts
  • .cursor/skills/react-hook-form-zod/templates/package.json
  • .cursor/skills/react-hook-form-zod/rules/react-hook-form-zod.md
  • .cursor/skills/react-hook-form-zod/templates/shadcn-form.tsx
  • .cursor/skills/react-hook-form-zod/templates/dynamic-fields.tsx
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/irc/implementation.ts
  • .cursor/skills/react-hook-form-zod/templates/server-validation.ts
  • src/shared/schemas/integrations/irc.ts
  • docs/ZOD.md
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/backend/**/*.{ts,tsx,js,jsx} : Mandatory Zod validation at boundaries in backend

Applied to files:

  • .cursor/skills/zod/AGENTS.md
  • src/features/integrations/lib/core/types.ts
  • .cursor/skills/react-hook-form-zod/templates/basic-form.tsx
  • .cursor/skills/designing-zod-schemas/SKILL.md
  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
  • src/app/api/integrations/[integration]/accounts/route.ts
  • .cursor/skills/react-hook-form-zod/SKILL.md
  • .cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx
  • .cursor/skills/react-hook-form-zod/templates/multi-step-form.tsx
  • src/shared/schemas/utils.ts
  • .cursor/skills/react-hook-form-zod/templates/package.json
  • .cursor/skills/react-hook-form-zod/templates/advanced-form.tsx
  • .cursor/skills/react-hook-form-zod/rules/react-hook-form-zod.md
  • .cursor/skills/react-hook-form-zod/templates/dynamic-fields.tsx
  • src/features/integrations/lib/core/base.ts
  • .cursor/skills/react-hook-form-zod/templates/server-validation.ts
  • src/shared/schemas/integrations/irc.ts
  • docs/ZOD.md
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/lib/*/keys.ts : Define module environment variables using t3-env `createEnv` with Zod schemas in module-level `keys.ts` files

Applied to files:

  • src/features/integrations/lib/core/types.ts
  • src/shared/schemas/utils.ts
  • docs/ZOD.md
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Use BetterAuth for all authentication operations

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/basic-form.tsx
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Use functional components and hooks in React code

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/basic-form.tsx
  • .cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx
  • .cursor/skills/react-hook-form-zod/templates/multi-step-form.tsx
  • .cursor/skills/react-hook-form-zod/rules/react-hook-form-zod.md
  • .cursor/skills/react-hook-form-zod/templates/dynamic-fields.tsx
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to {src/app/**,src/components/**}/*.{ts,tsx} : Use useUsers(), useUser(), useSessions(), useAdminStats(), useUpdateUser(), useDeleteUser(), useDeleteSession() hooks from src/hooks/use-admin.ts for standard queries

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/basic-form.tsx
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `async/await` syntax instead of promise chains for better readability

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to {src/app/**,src/components/**}/*.{ts,tsx} : Use corresponding Suspense hooks (useUsersSuspense(), useUserSuspense(), etc.) from src/hooks/use-admin-suspense.ts when wrapping components in Suspense and Error Boundaries

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
  • .cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Handle errors appropriately in async code with try-catch blocks

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx} : Avoid done callbacks in async tests - use async/await instead

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Server Components for async data fetching instead of async Client Components

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/app/**/*.{tsx} : Prefetch only critical data that users will definitely see, using Promise.all() for parallel prefetching instead of sequential await

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/async-validation.tsx
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to {src/app/**,src/components/**}/*.{tsx} : Wrap Suspense queries in ErrorBoundary component to automatically handle error propagation from useSuspenseQuery hooks

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/app/**/*.{ts,tsx} : Implement proper error boundaries in Next.js App Router pages and layouts

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/error*.{ts,tsx,js,jsx} : Errors must have a uniform shape in backend

Applied to files:

  • .cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to {src/app/**,src/components/**}/*.{tsx} : In regular query hooks, check isPending first, then isError, then use data to ensure TypeScript type narrowing works correctly

Applied to files:

  • .cursor/skills/react-hook-form-zod/rules/react-hook-form-zod.md
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/app/**/*.{tsx} : In Server Components, create a QueryClient per request using getServerQueryClient(), prefetch data in parallel with Promise.all(), and dehydrate using dehydrate(queryClient)

Applied to files:

  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/lib/api/server-queries.ts : Server-side query functions in src/lib/api/server-queries.ts must use direct database access via ORM instead of HTTP requests

Applied to files:

  • src/features/integrations/lib/xmpp/implementation.ts
📚 Learning: 2026-01-15T06:15:18.973Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/sentry.mdc:0-0
Timestamp: 2026-01-15T06:15:18.973Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Import Sentry using `import * as Sentry from "sentry/nextjs"` when using logs in NextJS projects

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:15:18.973Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/sentry.mdc:0-0
Timestamp: 2026-01-15T06:15:18.973Z
Learning: Applies to {instrumentation-client.{js,ts},sentry.server.config.{js,ts},sentry.edge.config.{js,ts}} : In NextJS projects, perform client-side Sentry initialization in `instrumentation-client.(js|ts)`, server initialization in `sentry.server.config.ts`, and edge initialization in `sentry.edge.config.ts` - do not repeat initialization in other files

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/app/**/*.{tsx} : Perform auth checks using Better Auth's auth.api.getSession() in Server Components before prefetching data, and redirect if not authenticated

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
  • .cursor/skills/react-hook-form-zod/templates/server-validation.ts
🧬 Code graph analysis (5)
src/app/api/integrations/[integration]/accounts/route.ts (1)
src/shared/api/utils.ts (1)
  • APIError (104-114)
.cursor/skills/react-hook-form-zod/templates/custom-error-display.tsx (1)
src/features/auth/lib/client.ts (1)
  • onError (50-59)
src/features/integrations/lib/xmpp/implementation.ts (1)
src/shared/schemas/integrations/xmpp.ts (2)
  • CreateXmppAccountRequestSchema (42-44)
  • UpdateXmppAccountRequestSchema (50-54)
src/shared/schemas/integrations/irc.ts (2)
src/shared/schemas/utils.ts (2)
  • brandedString (52-54)
  • metadataSchema (25-28)
src/shared/db/schema/irc.ts (1)
  • selectIrcAccountSchema (55-55)
src/features/integrations/hooks/use-integration.ts (1)
src/features/integrations/api/integrations.ts (2)
  • createIntegrationAccount (89-116)
  • updateIntegrationAccount (121-151)
🪛 markdownlint-cli2 (0.20.0)
.cursor/skills/designing-zod-schemas/SKILL.md

[warning] 41-41: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 103-103: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 117-117: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 135-135: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 143-143: Bare URL used

(MD034, no-bare-urls)

.cursor/skills/react-hook-form-zod/SKILL.md

[warning] 25-25: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 25-25: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 25-25: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 25-25: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 25-25: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 25-25: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 25-25: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 25-25: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)

.cursor/skills/react-hook-form-zod/rules/react-hook-form-zod.md

[warning] 41-41: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 41-41: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 103-103: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 117-117: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 117-117: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 125-125: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 135-135: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

docs/ZOD.md

[warning] 28-28: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 130-130: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (2)
  • GitHub Check: Seer Code Review
  • GitHub Check: cubic · AI code reviewer

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

…se types

- update handleAPIError to return human-readable zod errors
- add getCreateSchema and getUpdateSchema to Integration interface
- implement base schema methods in IntegrationBase
- add drizzle-zod and zod-validation-error dependencies
- add UpdateUserSelfSchema for profile updates
- add UserSearchSchema for admin user filtering
- add AdminUpdateUserSchema for administrative updates
- export schemas from central registry
- use UpdateUserSelfSchema in /api/user/me (PATCH)
- use UserSearchSchema in /api/admin/users (GET)
- use AdminUpdateUserSchema in /api/admin/users/[id] (PATCH)
- apply handleAPIError for consistent error responses
- refactor IntegrationManagement to use react-hook-form and zodResolver
- update IntegrationsContent to pass schema methods to components
- enhance /api/integrations/[integration]/accounts to use dynamic schema validation
- implement getCreateSchema and getUpdateSchema in IRC and XMPP integrations
- add human-readable error and form validation sections to ZOD.md
- update API.md with new error formats and schema-backed endpoints
- update INTEGRATIONS.md with schema methods and type inference patterns
Copy link

@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.

5 issues found across 18 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="docs/API.md">

<violation number="1" location="docs/API.md:78">
P3: Remove the stray ``` line after the note; it opens an unclosed code block and breaks markdown formatting for the remaining sections.</violation>

<violation number="2" location="docs/API.md:288">
P3: Fix the date format typo in the request body example (ISO 8601).</violation>

<violation number="3" location="docs/API.md:726">
P3: The error response format example is invalid JSON because the opening `{` was removed. Add the opening brace back so the documentation shows a valid response example.</violation>
</file>

<file name="docs/ZOD.md">

<violation number="1" location="docs/ZOD.md:338">
P3: The Type-Safe Integration Hooks example is missing a closing code fence, so the new "### 9. API Response Validation" heading renders inside the code block. Close the fence before the heading to restore proper markdown structure.</violation>
</file>

<file name="src/shared/schemas/user.ts">

<violation number="1" location="src/shared/schemas/user.ts:49">
P1: Invalid date strings will silently produce Invalid Date objects. `new Date("invalid")` doesn't throw - it returns a Date where `getTime()` is NaN. Add validation using `z.string().datetime()` or add a refine check for valid dates before transformation.</violation>
</file>

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

Copy link

@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: 6

Caution

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

⚠️ Outside diff range comments (1)
src/app/(dashboard)/app/integrations/integrations-content.tsx (1)

104-111: ⚠️ Potential issue | 🟡 Minor

Minor: Textarea not cleaned up if execCommand fails.

If execCommand("copy") returns false (line 108), the error is thrown before removeChild (line 111), leaving the textarea in the DOM.

🧹 Suggested fix
                              const ta = document.createElement("textarea");
                              ta.value = ircPasswordDialog.temporaryPassword;
                              document.body.appendChild(ta);
                              ta.select();
-                             if (!document.execCommand("copy")) {
-                               throw new Error("execCommand copy failed");
-                             }
-                             document.body.removeChild(ta);
+                             const success = document.execCommand("copy");
+                             document.body.removeChild(ta);
+                             if (!success) {
+                               throw new Error("execCommand copy failed");
+                             }
🤖 Fix all issues with AI agents
In `@docs/API.md`:
- Line 288: Update the documentation entry for the "banExpires" field to correct
the ISO standard typo: change the string value from "ISO 8061 date" to "ISO 8601
date" wherever the "banExpires" example/description appears (search for the
literal "banExpires" in docs/API.md to locate all occurrences).
- Around line 87-88: Remove the stray closing code fence that is ending a
non-existent code block so the "**Note:** The `details` field..." line is
rendered as normal text; specifically edit the docs/API.md entry containing the
"**Note:**" line to delete the trailing "```" so the paragraph is not inside a
code block.

In `@docs/INTEGRATIONS.md`:
- Around line 174-177: Docs list getCreateSchema and getUpdateSchema as optional
getter functions, but the implementation exposes schema properties named
createAccountSchema and updateAccountSchema; update the docs to match the code
by replacing references to getCreateSchema/getUpdateSchema with the actual
property names createAccountSchema and updateAccountSchema (and document their
types as z.ZodType<TCreateInput> / z.ZodType<TUpdateInput> respectively), or
alternatively modify the implementation to provide getters named
getCreateSchema/getUpdateSchema; reference the symbols createAccountSchema,
updateAccountSchema, getCreateSchema, and getUpdateSchema when making the change
so the docs and code agree.

In `@docs/ZOD.md`:
- Around line 323-338: The "Type-Safe Integration Hooks" section stops
mid-example and needs a completed call-site illustration showing how Zod schemas
flow into the hook; finish the example by demonstrating creating the input value
that matches CreateAccountInput and passing it into useCreateIntegrationAccount
(reference CreateAccountSchema, CreateAccountInput, and
useCreateIntegrationAccount) so readers can see the full flow from schema ->
inferred type -> hook invocation and a sample call (e.g., calling
mutation.mutate or similar) to show type safety at the call site.

In `@src/features/integrations/components/integration-management.tsx`:
- Around line 96-114: The onSubmit handler can submit an empty payload {} when
neither createSchema nor createInputToPayload are provided; update onSubmit to
guard against this by checking if both createSchema and createInputToPayload are
falsy and the trimmed input is empty, then prevent submission (return early) and
surface a validation error (e.g., call the form's setError / show a user-facing
message) instead of sending an empty object. Modify the onSubmit function and
use the existing symbols createInputName, createInputToPayload, createSchema and
trimmed to implement this early-return validation so an empty payload is never
submitted.

In `@src/shared/schemas/user.ts`:
- Line 9: selectUserSchema created via createSelectSchema(user) will fail at
runtime due to a drizzle-orm/drizzle-zod version mismatch: upgrade or align the
Drizzle packages so internals like selectedFields exist. Fix by ensuring
drizzle-orm, drizzle-kit and drizzle-zod use the same release line—either
downgrade drizzle-orm to a stable 0.36+/0.44.x series that matches
drizzle-zod@0.8.3, or instead install a beta-matched drizzle-zod build that
corresponds to your drizzle-orm@1.0.0-beta commit; update package.json (and
lockfile), reinstall and rebuild, then verify createSelectSchema(user) and
selectUserSchema work without runtime errors.
🧹 Nitpick comments (11)
src/features/integrations/lib/xmpp/implementation.ts (1)

127-164: Consider adding explicit schema validation in createAccount.

Unlike the IRC implementation which uses CreateIrcAccountRequestSchema.safeParse(input) at the method entry, the XMPP createAccount relies on determineUsername for validation. While functional, explicit schema validation at the boundary would be more consistent with the IRC pattern and the coding guidelines for mandatory Zod validation at boundaries.

♻️ Suggested validation pattern
   async createAccount(
     userId: string,
     input: CreateXmppAccountRequest
   ): Promise<XmppAccount> {
     if (!this.enabled) {
       throw new Error("XMPP integration is not configured");
     }
+    const parsed = CreateXmppAccountRequestSchema.safeParse(input);
+    if (!parsed.success) {
+      const msg = parsed.error.issues[0]?.message ?? "Invalid input";
+      throw new Error(msg);
+    }
+    const { username: providedUsername } = parsed.data;
     validateXmppConfig();
src/app/api/integrations/[integration]/accounts/route.ts (2)

46-52: Consider handling output validation errors gracefully.

Using .parse() for outgoing data validation (line 49) will throw a ZodError if the account doesn't match the schema. This could result in 500 errors if there's a schema/data mismatch. Consider using .safeParse() and logging mismatches while still returning the data, or catching specifically to avoid leaking internal details.

♻️ Safer output validation
     let data = account;
     if (integration.accountSchema) {
-      // Validate outgoing data against schema (ensure no leaks)
-      data = integration.accountSchema.parse(account);
+      // Validate outgoing data against schema (ensure no leaks)
+      const parsed = integration.accountSchema.safeParse(account);
+      if (!parsed.success) {
+        // Log the mismatch but don't fail the request
+        Sentry.captureException(new Error('Account schema validation failed'), {
+          extra: { integrationId, issues: parsed.error.issues },
+        });
+      } else {
+        data = parsed.data;
+      }
     }

117-121: Same concern: output validation could throw unexpectedly.

The same pattern as the GET handler - consider using safeParse for defensive output validation to avoid 500 errors on schema mismatches.

src/features/integrations/components/integration-management.tsx (3)

47-48: Consider adding @deprecated JSDoc annotation.

The createInputRequired prop is deprecated per the comment on line 68, but the interface doesn't reflect this. Adding a JSDoc annotation would provide IDE warnings to consumers.

📝 Suggested documentation improvement
-  createInputRequired?: boolean;
-  createInputToPayload?: (value: string) => Record<string, unknown>;
+  /** `@deprecated` Use createSchema with required field instead */
+  createInputRequired?: boolean;
+  /** `@deprecated` Provide createSchema for validation; payload is derived from form data */
+  createInputToPayload?: (value: string) => Record<string, unknown>;

83-94: Consider typing the form data shape for better type safety.

The form uses Record<string, string> for the data type in onSubmit, but this loses the connection to the schema's expected shape. While the any cast is necessary for the resolver, you could improve type inference for consumers.

📝 Suggested type improvement
+  type FormValues = { [key: string]: string };
+
   const {
     register,
     handleSubmit,
     formState: { errors },
     reset,
-  } = useForm({
+  } = useForm<FormValues>({
     // biome-ignore lint/suspicious/noExplicitAny: Resolver type mismatch workaround
     resolver: createSchema ? zodResolver(createSchema as any) : undefined,
     defaultValues: {
       [createInputName]: "",
     },
   });

191-201: Consider adding aria-describedby for accessibility.

When validation errors are present, screen readers should announce them in relation to the input field. Link the error message to the input using aria-describedby.

♿ Accessibility improvement
+                const errorId = `${integrationId}-${createInputName}-error`;
                 <Input
                   disabled={createMutation.isPending}
                   id={`${integrationId}-${createInputName}`}
                   placeholder={createInputPlaceholder}
+                  aria-invalid={!!errors[createInputName]}
+                  aria-describedby={errors[createInputName] ? errorId : undefined}
                   {...register(createInputName)}
                 />
                 {errors[createInputName]?.message && (
-                  <p className="font-medium text-destructive text-sm">
+                  <p id={errorId} className="font-medium text-destructive text-sm" role="alert">
                     {String(errors[createInputName]?.message)}
                   </p>
                 )}
docs/ZOD.md (2)

297-299: Missing code example for JSONB handling.

Best Practice #6 mentions handling JSONB fields with .transform() and metadataSchema.parse() but doesn't provide a concrete example. Adding an example would make this guidance more actionable.

📝 Suggested example to add
 ### 6. Handle JSONB Fields Properly

 drizzle-zod generates `unknown` for JSONB fields. Use `.transform()` and `metadataSchema.parse()` to properly type and validate them:
+
+```typescript
+import { metadataSchema } from "@/shared/schemas/utils";
+
+export const IrcAccountSchema = selectIrcAccountSchema
+  .transform((data) => ({
+    ...data,
+    // Validate and type the JSONB metadata field
+    metadata: data.metadata 
+      ? metadataSchema.parse(data.metadata) 
+      : undefined,
+  }));
+```

461-479: Clarify async .refine() usage.

The example shows an async .refine() for checking nick availability (lines 472-477), which is a valid pattern. However, it's important to note that schemas with async refinements must be parsed using .parseAsync() or .safeParseAsync() instead of the synchronous .parse() or .safeParse() methods. Consider adding this clarification to help developers avoid runtime errors.

📝 Suggested clarification
       "Nick already taken"
     ),
 });
+
+// Note: Schemas with async refinements must use parseAsync
+const result = await CreateIrcAccountRequestSchema.parseAsync(input);
+// OR
+const result = await CreateIrcAccountRequestSchema.safeParseAsync(input);

</details>

</blockquote></details>
<details>
<summary>src/shared/api/utils.ts (1)</summary><blockquote>

`102-107`: **Remove duplicate JSDoc comment block.**

There are two consecutive JSDoc comments for the `APIError` class. Remove the first one (lines 102-104) as it's redundant.


<details>
<summary>🧹 Proposed fix</summary>

```diff
-/**
- * Custom API Error class
- */
 /**
  * Custom API Error class
  */
 export class APIError extends Error {
src/shared/schemas/user.ts (1)

47-50: Consider validating date string format before transformation.

The banExpires field transforms any string to a Date, but invalid date strings will produce Invalid Date. Consider adding validation to ensure the string is a valid ISO 8601 date before transformation.

🛡️ Proposed fix with date validation
   banExpires: z
     .string()
-    .transform((val) => (val ? new Date(val) : undefined))
+    .refine((val) => !val || !Number.isNaN(Date.parse(val)), {
+      message: "Invalid date format",
+    })
+    .transform((val) => (val ? new Date(val) : undefined))
     .optional(),
src/app/api/admin/users/route.ts (1)

48-59: Pagination count query is inefficient - fetches all rows.

The current count implementation fetches all matching rows to count them:

const total = await db.select({ count: user.id }).from(user).where(whereClause);
// total.length gives count

For large datasets, this is inefficient. Consider using SQL COUNT(*) for better performance.

⚡ Proposed fix using SQL COUNT
+import { count } from "drizzle-orm";
+
-    const total = await db
+    const [{ totalCount }] = await db
-      .select({ count: user.id })
+      .select({ totalCount: count() })
       .from(user)
       .where(whereClause);

     return Response.json({
       users,
       pagination: {
-        total: total.length,
+        total: totalCount,
         limit,
         offset,
-        hasMore: offset + limit < total.length,
+        hasMore: offset + limit < totalCount,
       },
     });
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1b8d70 and c1d65d8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • docs/API.md
  • docs/INTEGRATIONS.md
  • docs/ZOD.md
  • package.json
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
  • src/app/api/admin/users/[id]/route.ts
  • src/app/api/admin/users/route.ts
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/app/api/user/me/route.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/base.ts
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/api/utils.ts
  • src/shared/schemas/index.ts
  • src/shared/schemas/user.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/shared/schemas/index.ts
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

**/*.{js,jsx,ts,tsx}: Use Sentry.captureException(error) to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected
Use Sentry.startSpan() function to create spans for meaningful actions within applications like button clicks, API calls, and function calls

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/base.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/shared/api/utils.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/api/user/me/route.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

When creating custom spans for API calls with Sentry.startSpan(), ensure the name and op properties are meaningful (e.g., op: "http.client" with descriptive names like GET /api/users/${userId}), and attach attributes based on relevant request information and metrics

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/base.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/shared/api/utils.ts
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/api/user/me/route.ts
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

**/*.{js,ts,jsx,tsx}: Import Sentry using import * as Sentry from "@sentry/nextjs" when using logs in NextJS projects
Reference the Sentry logger using const { logger } = Sentry when using logging functionality
Use logger.fmt as a template literal function to bring variables into structured logs, providing better log formatting and variable interpolation

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/base.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/shared/api/utils.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/api/user/me/route.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
**/*.{css,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/tailwind-v4.mdc)

Use container query support with @container, @sm:, @md: for container-based breakpoints and @max-md: for max-width queries

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/base.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/shared/api/utils.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/api/user/me/route.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
**/*.{ts,tsx,js,jsx,html}

📄 CodeRabbit inference engine (.cursor/rules/tailwind-v4.mdc)

**/*.{ts,tsx,js,jsx,html}: Use 3D transform utilities: transform-3d, rotate-x-*, rotate-y-*, rotate-z-*, scale-z-*, translate-z-*, perspective-*, and perspective-origin-*
Use linear gradient angles with bg-linear-45 syntax and gradient interpolation like bg-linear-to-r/oklch or bg-linear-to-r/srgb
Use conic and radial gradients with bg-conic and bg-radial-[at_25%_25%] utilities
Use inset-shadow-* and inset-ring-* utilities instead of deprecated shadow opacity utilities
Use field-sizing-content utility for auto-resizing textareas
Use scheme-light and scheme-dark utilities for color-scheme property
Use font-stretch-* utilities for variable font configuration
Chain variants together for composable variants (e.g., group-has-data-potato:opacity-100)
Use starting variant for @starting-style transitions
Use not-* variant for :not() pseudo-class (e.g., not-first:mb-4)
Use inert variant for styling elements with the inert attribute
Use nth-* variants: nth-3:, nth-last-5:, nth-of-type-4:, nth-last-of-type-6: for targeting specific elements
Use in-* variant as a simpler alternative to group-* without adding group class
Use open variant to support :popover-open pseudo-class
Use ** variant for targeting all descendants
Replace deprecated bg-opacity-* utilities with color values using slash notation (e.g., bg-black/50)
Replace deprecated text-opacity-* utilities with color values using slash notation (e.g., text-black/50)
Replace deprecated border-opacity-*, divide-opacity-* and similar opacity utilities with color slash notation
Use shadow-xs instead of shadow-sm and shadow-sm instead of shadow
Use drop-shadow-xs instead of drop-shadow-sm and drop-shadow-sm instead of drop-shadow
Use blur-xs instead of blur-sm and blur-sm instead of blur
Use rounded-xs instead of rounded-sm and rounded-sm instead of rounded
Use outline-hidden instead of outline-none for...

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/base.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/shared/api/utils.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/api/user/me/route.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/tanstack-query.mdc)

**/*.{ts,tsx}: Create QueryClient using getQueryClient() function that automatically handles server/client isolation (new instance per server request, singleton on client)
Always use the centralized query key factory from src/lib/api/query-keys.ts instead of creating keys manually
Include all variables used in queryFn in the query key to ensure proper cache management and query invalidation

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

**/*.{ts,tsx}: Use TypeScript strict mode with explicit types; prefer unknown over any
Use functional components and hooks in React code
Use selective imports over barrel exports for performance
Follow Next.js App Router conventions
Always await promises in async functions
Use semantic HTML and ARIA attributes for accessibility
Import authentication operations from @/auth module using barrel exports
Import database operations from @/db module using barrel exports
Import app configuration from @/config or @/config/app using barrel exports
Import UI components using direct imports from @/components/ui/* (e.g., @/components/ui/button)
Import custom hooks using direct imports from @/hooks/* (e.g., @/hooks/use-permissions)
Centralize major types in src/types/ directory: use @/types/auth, @/types/api, @/types/routes, @/types/email, @/types/common for imports
Import major constants from @/lib/utils/constants.ts: USER_ROLES, PERMISSIONS, HTTP_STATUS, API_ERROR_CODES, QUERY_CACHE, RATE_LIMIT, INTEGRATION_STATUSES, PAGINATION, VALIDATION_PATTERNS, MOBILE_BREAKPOINT, DATE_FORMATS
Use TanStack Query for all server state management and data fetching
Optimize images with next/image component instead of HTML img tags
Validate all input...

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/base.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/shared/api/utils.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/api/user/me/route.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
{src/app/**,src/components/**}/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/tanstack-query.mdc)

{src/app/**,src/components/**}/*.{ts,tsx}: Use useUsers(), useUser(), useSessions(), useAdminStats(), useUpdateUser(), useDeleteUser(), useDeleteSession() hooks from src/hooks/use-admin.ts for standard queries
Use corresponding Suspense hooks (useUsersSuspense(), useUserSuspense(), etc.) from src/hooks/use-admin-suspense.ts when wrapping components in Suspense and Error Boundaries

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/app/api/admin/users/route.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/app/api/user/me/route.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{ts,tsx,js,jsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Use function components over class components
Call hooks at the top level only, never conditionally
Specify all dependencies in hook dependency arrays correctly
Use the key prop for elements in iterables (prefer unique IDs over array indices)
Nest children between opening and closing tags instead of passing as props in React components
Don't define components inside other components
Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, and use semantic elements instead of divs with roles
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Keep functions focused and under reasonable cognitive complexity limits
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Group related code together and separate concerns
Add `...

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/base.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/shared/api/utils.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/api/user/me/route.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
**/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/app/**/*.{ts,tsx}: Implement proper error boundaries in Next.js App Router pages and layouts
Use Suspense for loading states in Next.js App Router components

Files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/app/api/admin/users/route.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/app/api/user/me/route.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)

When creating custom spans for component actions with Sentry.startSpan(), ensure the name and op properties are meaningful for the activities in the call, and attach attributes based on relevant information and metrics

Files:

  • src/features/integrations/components/integration-management.tsx
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Validate all inputs with Zod schemas
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/backend/**/*.{ts,tsx,js,jsx} : Mandatory Zod validation at boundaries in backend
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Validate all inputs with Zod schemas

Applied to files:

  • docs/INTEGRATIONS.md
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/base.ts
  • docs/ZOD.md
  • src/shared/api/utils.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/backend/**/*.{ts,tsx,js,jsx} : Mandatory Zod validation at boundaries in backend

Applied to files:

  • docs/INTEGRATIONS.md
  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/core/base.ts
  • docs/ZOD.md
  • src/shared/api/utils.ts
  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/core/types.ts
  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Centralize major types in `src/types/` directory: use `@/types/auth`, `@/types/api`, `@/types/routes`, `@/types/email`, `@/types/common` for imports

Applied to files:

  • docs/INTEGRATIONS.md
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/types.ts
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/*route*.{ts,tsx,js,jsx} : Clean, non-duplicated REST routes in backend code

Applied to files:

  • docs/INTEGRATIONS.md
  • src/app/api/admin/users/[id]/route.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/lib/*/keys.ts : Define module environment variables using t3-env `createEnv` with Zod schemas in module-level `keys.ts` files

Applied to files:

  • docs/INTEGRATIONS.md
  • src/shared/schemas/user.ts
  • src/features/integrations/lib/core/types.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/lib/api/types.ts : TypeScript types for resources must be derived from database schema and include type interfaces for list filters (e.g., UserListFilters, PostListFilters)

Applied to files:

  • docs/INTEGRATIONS.md
  • src/shared/schemas/user.ts
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/api/**/*.{ts,tsx,js,jsx} : API, DB, auth contracts, or tokens require mandatory review

Applied to files:

  • docs/INTEGRATIONS.md
  • src/app/api/integrations/[integration]/accounts/route.ts
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Handle errors appropriately in async code with try-catch blocks

Applied to files:

  • src/app/api/integrations/[integration]/accounts/route.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/lib/api/admin.ts : All API query functions must throw errors (not return undefined) and check response.ok for fetch() calls with proper error handling

Applied to files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/api/utils.ts
📚 Learning: 2025-12-18T18:18:05.202Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/anti-slop.mdc:0-0
Timestamp: 2025-12-18T18:18:05.202Z
Learning: Applies to **/error*.{ts,tsx,js,jsx} : Errors must have a uniform shape in backend

Applied to files:

  • src/app/api/integrations/[integration]/accounts/route.ts
  • src/shared/api/utils.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/app/**/*.{tsx} : In Server Components, create a QueryClient per request using getServerQueryClient(), prefetch data in parallel with Promise.all(), and dehydrate using dehydrate(queryClient)

Applied to files:

  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/lib/api/server-queries.ts : Server-side query functions in src/lib/api/server-queries.ts must use direct database access via ORM instead of HTTP requests

Applied to files:

  • src/features/integrations/lib/xmpp/implementation.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import database operations from `@/db` module using barrel exports

Applied to files:

  • src/features/integrations/lib/xmpp/implementation.ts
  • src/app/api/admin/users/route.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to **/*.{ts,tsx} : Create QueryClient using getQueryClient() function that automatically handles server/client isolation (new instance per server request, singleton on client)

Applied to files:

  • src/features/integrations/lib/xmpp/implementation.ts
  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to {src/app/**,src/components/**}/*.{ts,tsx} : Use useUsers(), useUser(), useSessions(), useAdminStats(), useUpdateUser(), useDeleteUser(), useDeleteSession() hooks from src/hooks/use-admin.ts for standard queries

Applied to files:

  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/features/integrations/components/integration-management.tsx
  • src/app/api/user/me/route.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import major constants from `@/lib/utils/constants.ts`: `USER_ROLES`, `PERMISSIONS`, `HTTP_STATUS`, `API_ERROR_CODES`, `QUERY_CACHE`, `RATE_LIMIT`, `INTEGRATION_STATUSES`, `PAGINATION`, `VALIDATION_PATTERNS`, `MOBILE_BREAKPOINT`, `DATE_FORMATS`

Applied to files:

  • src/app/api/admin/users/route.ts
  • src/shared/schemas/user.ts
  • src/shared/api/utils.ts
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/app/**/*.{tsx} : Perform auth checks using Better Auth's auth.api.getSession() in Server Components before prefetching data, and redirect if not authenticated

Applied to files:

  • src/app/api/admin/users/route.ts
  • src/app/api/admin/users/[id]/route.ts
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to {src/app/**,src/components/**}/*.{ts,tsx} : Use corresponding Suspense hooks (useUsersSuspense(), useUserSuspense(), etc.) from src/hooks/use-admin-suspense.ts when wrapping components in Suspense and Error Boundaries

Applied to files:

  • src/app/api/admin/users/route.ts
  • src/features/integrations/components/integration-management.tsx
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Import authentication operations from `@/auth` module using barrel exports

Applied to files:

  • src/shared/schemas/user.ts
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Use functional components and hooks in React code

Applied to files:

  • src/features/integrations/components/integration-management.tsx
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-01-15T06:15:18.973Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/sentry.mdc:0-0
Timestamp: 2026-01-15T06:15:18.973Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Import Sentry using `import * as Sentry from "sentry/nextjs"` when using logs in NextJS projects

Applied to files:

  • src/features/integrations/components/integration-management.tsx
  • src/features/integrations/lib/irc/implementation.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/app/**/*.{ts,tsx} : Use Suspense for loading states in Next.js App Router components

Applied to files:

  • src/features/integrations/components/integration-management.tsx
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to src/app/providers.tsx : Include ReactQueryDevtools in src/app/providers.tsx with NODE_ENV === 'development' check for development-only access

Applied to files:

  • src/features/integrations/components/integration-management.tsx
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-01-15T06:15:18.973Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/sentry.mdc:0-0
Timestamp: 2026-01-15T06:15:18.973Z
Learning: Applies to {instrumentation-client.{js,ts},sentry.server.config.{js,ts},sentry.edge.config.{js,ts}} : In NextJS projects, perform client-side Sentry initialization in `instrumentation-client.(js|ts)`, server initialization in `sentry.server.config.ts`, and edge initialization in `sentry.edge.config.ts` - do not repeat initialization in other files

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:15:18.973Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/sentry.mdc:0-0
Timestamp: 2026-01-15T06:15:18.973Z
Learning: Applies to **/*.{js,ts,jsx,tsx} : Reference the Sentry logger using `const { logger } = Sentry` when using logging functionality

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-02-01T01:00:48.715Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-01T01:00:48.715Z
Learning: Applies to **/*.{ts,tsx} : Never expose API keys in client code; keep sensitive credentials server-side only

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Server Components for async data fetching instead of async Client Components

Applied to files:

  • src/features/integrations/lib/irc/implementation.ts
📚 Learning: 2026-01-15T06:16:30.014Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2026-01-15T06:16:30.014Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use proper image components (e.g., Next.js `<Image>`) over `<img>` tags

Applied to files:

  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-01-15T06:16:09.034Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/tanstack-query.mdc:0-0
Timestamp: 2026-01-15T06:16:09.034Z
Learning: Applies to {src/app/**,src/components/**}/*.{tsx} : Wrap Suspense queries in ErrorBoundary component to automatically handle error propagation from useSuspenseQuery hooks

Applied to files:

  • src/app/(dashboard)/app/integrations/integrations-content.tsx
📚 Learning: 2026-01-15T06:15:18.973Z
Learnt from: CR
Repo: allthingslinux/portal PR: 0
File: .cursor/rules/sentry.mdc:0-0
Timestamp: 2026-01-15T06:15:18.973Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use `Sentry.captureException(error)` to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected

Applied to files:

  • src/app/(dashboard)/app/integrations/integrations-content.tsx
🧬 Code graph analysis (8)
src/app/api/integrations/[integration]/accounts/route.ts (2)
src/shared/db/schema/auth.ts (1)
  • account (48-70)
src/shared/api/utils.ts (1)
  • APIError (108-121)
src/features/integrations/lib/xmpp/implementation.ts (2)
src/shared/schemas/integrations/xmpp.ts (4)
  • CreateXmppAccountRequestSchema (42-44)
  • UpdateXmppAccountRequestSchema (50-54)
  • XmppAccountSchema (60-63)
  • XmppAccount (76-76)
src/features/integrations/lib/xmpp/types.ts (1)
  • XmppAccount (11-11)
src/app/api/admin/users/route.ts (1)
src/shared/schemas/user.ts (1)
  • UserSearchSchema (56-65)
src/app/api/admin/users/[id]/route.ts (1)
src/shared/schemas/user.ts (1)
  • AdminUpdateUserSchema (41-51)
src/features/integrations/components/integration-management.tsx (4)
src/components/ui/card.tsx (2)
  • CardContent (91-91)
  • CardFooter (87-87)
src/components/ui/label.tsx (1)
  • Label (24-24)
src/components/ui/input.tsx (1)
  • Input (21-21)
src/components/ui/button.tsx (1)
  • Button (64-64)
src/features/integrations/lib/irc/implementation.ts (2)
src/shared/schemas/integrations/irc.ts (4)
  • CreateIrcAccountRequestSchema (51-53)
  • UpdateIrcAccountRequestSchema (59-63)
  • IrcAccountSchema (69-73)
  • IrcAccount (86-86)
src/features/integrations/lib/irc/types.ts (1)
  • IrcAccount (11-11)
src/app/api/user/me/route.ts (1)
src/shared/schemas/user.ts (1)
  • UpdateUserSelfSchema (33-36)
src/app/(dashboard)/app/integrations/integrations-content.tsx (2)
src/shared/schemas/integrations/irc.ts (1)
  • CreateIrcAccountRequestSchema (51-53)
src/shared/schemas/integrations/xmpp.ts (1)
  • CreateXmppAccountRequestSchema (42-44)
🪛 GitHub Check: Test
src/shared/schemas/user.ts

[failure] 9-9: tests/app/api/user/me/route.test.ts
TypeError: Cannot read properties of undefined (reading 'selectedFields')
❯ getViewSelectedFields node_modules/.pnpm/drizzle-orm@1.0.0-beta.8-734e789_@opentelemetry+api@1.9.0_@types+mssql@9.1.9_@types+pg@bd49458e3431ab18b86daac3b0125a49/node_modules/drizzle-orm/utils.js:112:31
❯ getColumns node_modules/.pnpm/drizzle-zod@0.8.3_drizzle-orm@1.0.0-beta.8-734e789
@opentelemetry+api@1.9.0_@types+mssq_477af087fe4345afc25b276bf2d32840/node_modules/drizzle-zod/index.mjs:241:62
❯ createSelectSchema node_modules/.pnpm/drizzle-zod@0.8.3_drizzle-orm@1.0.0-beta.8-734e789_@opentelemetry+api@1.9.0_@types+mssq_477af087fe4345afc25b276bf2d32840/node_modules/drizzle-zod/index.mjs:299:21
❯ src/shared/schemas/user.ts:9:33
❯ src/app/api/user/me/route.ts:12:1

🪛 markdownlint-cli2 (0.20.0)
docs/ZOD.md

[warning] 28-28: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 130-130: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

docs/API.md

[warning] 88-88: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (2)
  • GitHub Check: Seer Code Review
  • GitHub Check: cubic · AI code reviewer
🔇 Additional comments (28)
src/features/integrations/lib/core/types.ts (1)

1-2: LGTM! Clean schema property additions to the Integration interface.

The optional schema properties (createAccountSchema, updateAccountSchema, accountSchema) are well-typed with proper generic bounds. The type-only import is correct since z.ZodType is only used in type positions.

Also applies to: 98-112

docs/INTEGRATIONS.md (1)

186-194: Good documentation of the schema-first type pattern.

The example correctly demonstrates inferring types from Zod schemas using z.infer, which aligns with the centralized schema approach in @/shared/schemas/integrations/irc.

src/features/integrations/lib/core/base.ts (2)

11-22: LGTM! Well-designed generic options interface.

The IntegrationBaseOptions correctly introduces generic parameters for schema types. Using z.ZodType<unknown> for accountSchema is a reasonable trade-off since TAccount isn't available at the options level - implementations must ensure type correctness.


34-48: Schema assignment and type casting are acceptable.

The cast on lines 46-48 is necessary because the options interface can't access TAccount. The approach is safe as long as implementations provide correctly-typed schemas, which is enforced by the generic constraints in the concrete integration classes.

src/features/integrations/lib/irc/implementation.ts (2)

17-21: LGTM! Proper migration to shared schemas.

The schema imports from @/shared/schemas/integrations/irc and constructor wiring are correct. The double cast on accountSchema (lines 42-44) is necessary because IrcAccountSchema doesn't inherently include the optional temporaryPassword field that's added during account creation - this is an acceptable trade-off.

Also applies to: 39-44


60-66: Good: Input validation at boundary with meaningful error message.

Using safeParse with proper error extraction aligns with the coding guidelines for mandatory Zod validation at boundaries.

src/features/integrations/lib/xmpp/implementation.ts (1)

28-32: LGTM! Clean migration to shared schemas.

The schema imports and constructor wiring follow the same pattern as IRC. The single cast for accountSchema is simpler here since XmppAccount doesn't have the temporary password complexity.

Also applies to: 50-53

src/app/api/integrations/[integration]/accounts/route.ts (1)

85-112: LGTM! Robust input validation with proper error handling.

The JSON parse error handling (lines 85-90) addresses the previous review concern. The schema validation flow correctly uses safeParse with detailed error information for clients, and the fallback for integrations without schemas is appropriately permissive.

src/app/(dashboard)/app/integrations/integrations-content.tsx (2)

24-25: LGTM! Clean schema-driven integration for IRC.

The shared schema import and props wiring (createInputName="nick", createSchema={CreateIrcAccountRequestSchema}) correctly align with the schema definition where nick is the required field.

Also applies to: 154-157


282-285: LGTM! Clean schema-driven integration for XMPP.

Same pattern as IRC - createInputName="username" matches the username field in CreateXmppAccountRequestSchema.

src/features/integrations/components/integration-management.tsx (5)

6-9: LGTM!

The imports for react-hook-form integration with Zod validation are correctly structured. Using type { ZodType } for the type-only import and the namespace import for Sentry follows the coding guidelines.


132-151: LGTM!

The delete handler correctly guards against null account, captures exceptions with Sentry, and provides appropriate user feedback via toast notifications.


153-161: LGTM!

Clean loading state implementation with appropriate visual feedback.


163-174: LGTM!

Error state provides clear visual feedback with the destructive color scheme.


241-298: LGTM!

The account management UI with the AlertDialog confirmation for deletion provides good UX and protects against accidental deletions. The status badge logic correctly handles the 'deleted' state variant.

docs/ZOD.md (8)

53-127: LGTM: Clear three-layer architecture explanation.

The explanation of the Database → Zod → TypeScript layers is well-structured, and the code examples correctly demonstrate:

  • Using drizzle-zod to generate base schemas
  • Extending schemas with custom validation
  • Using .transform() to handle JSONB typing
  • Inferring TypeScript types with z.infer

155-174: Excellent trust boundary guidance.

The three-tier trust model (Untrusted → Sort-of Trusted → Trusted) provides clear, actionable guidance on when to apply Zod validation. This aligns perfectly with the mandatory validation requirements at API boundaries. Based on learnings, all inputs at backend boundaries must be validated with Zod schemas, which this section clearly mandates for untrusted inputs.


176-204: LGTM: Clear decision criteria.

The "When to Use What" section provides clear, actionable criteria for choosing between Drizzle schemas, drizzle-zod generated schemas, custom Zod schemas, and TypeScript types. The emphasis on never manually defining types (line 203) is particularly important for maintaining a single source of truth.


338-409: LGTM: Solid best practices for validation, error handling, and forms.

The remaining best practices cover critical aspects:

  • API Response Validation (lines 338-364): Excellent security practice showing how to prevent data leakage by validating outbound responses
  • Structured Error Handling (lines 366-396): Proper integration of zod-validation-error for user-friendly error messages
  • Client-Side Form Validation (lines 398-409): Standardizes on react-hook-form with zodResolver, which is compatible with React 19 and provides a consistent pattern

415-495: LGTM: Comprehensive examples covering common patterns.

The three examples effectively demonstrate:

  • Example 1: Complete CRUD schema pattern with proper use of .omit(), .extend(), .pick(), and .partial()
  • Example 2: Complex validation with regex patterns and custom refinements
  • Example 3: Nested object validation with optional fields and defaults

All patterns are compatible with Zod v4.


497-570: LGTM: Clear and actionable migration guide.

The four-step migration guide provides a straightforward path for adopting the Zod-first approach:

  1. Add drizzle-zod schema generation
  2. Create custom validation schemas by extending base schemas
  3. Replace manual interfaces with z.infer types
  4. Update implementations to use schema validation

Each step includes clear before/after examples that make the migration path obvious.


571-583: LGTM: Appropriate cross-references and external resources.

The documentation properly links to:

  • Related internal documentation (API, Architecture, Integrations, TypeScript config)
  • Official Zod and drizzle-zod documentation
  • The Total TypeScript article referenced in the trust boundaries section

301-321: No action needed. The brandedString helper is correctly exported from @/shared/schemas/utils (defined at line 52-53 of src/shared/schemas/utils.ts), and the documentation example accurately reflects its usage in the codebase.

package.json (1)

97-97: LGTM! Dependencies align with the Zod centralization goals.

The addition of drizzle-zod for schema generation and zod-validation-error for human-readable error messages supports the PR's objective of centralizing validation logic.

Also applies to: 124-125

src/shared/api/utils.ts (1)

139-150: LGTM! Automatic Zod error handling with human-readable messages.

The implementation correctly:

  • Detects Zod-like errors using isZodErrorLike
  • Converts to human-readable messages via fromError
  • Returns appropriate 400 status for validation failures

One consideration: exposing error.issues in details provides useful debugging info but may reveal schema structure to clients. This appears intentional per the API documentation, which is acceptable for this use case.

src/app/api/admin/users/[id]/route.ts (1)

63-68: LGTM! Schema validation properly applied at API boundary.

The route correctly:

  • Validates request body with AdminUpdateUserSchema.parse() before any database operations
  • Spreads only validated fields into the update (safe because schema defines allowed fields)
  • Relies on handleAPIError to catch and format Zod validation errors

This aligns with the coding guidelines requiring Zod validation at boundaries. Based on learnings: "Mandatory Zod validation at boundaries in backend".

src/app/api/admin/users/route.ts (1)

16-18: LGTM! Query parameters validated with schema.

Using UserSearchSchema.parse(Object.fromEntries(searchParams)) properly validates and transforms query parameters with defaults applied. This is a clean pattern for handling search/filter params.

src/app/api/user/me/route.ts (1)

82-97: LGTM! Schema validation properly enforces allowed update fields.

The implementation correctly:

  • Validates request body with UpdateUserSelfSchema.parse() at the API boundary
  • Schema enforces only name and image fields can be updated (matching the comment on line 93)
  • Spreads validated fields safely into the database update

This aligns with the coding guidelines requiring Zod validation at boundaries. Based on learnings: "Validate all inputs with Zod schemas".

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

- mock @/shared/schemas/user to prevent drizzle-zod crash
- ensure database mocks don't conflict with schema generation
- upgrade drizzle-zod to 1.0.0-beta.8-734e789
- resolve runtime incompatibility with selectedFields internal property
- check for empty input when no schema or payload converter is provided
- use setError to show validation message
- prevent submitting empty object {} to the API
- Fix typos and align property names in API/Integration docs
- Add ARIA attributes and type safety to IntegrationManagement
- Fix DOM cleanup in clipboard copy logic
- Add boundary validation to XMPP and safe output parsing for integrations
- Optimize admin user list count query
- Refine user schema for banExpires date validation
- Passed all 68 tests across 13 files
- Fix missing brace in API.md error example
- Refine date validation in user schema to catch NaN
- Fix unsafe isNaN lint error
- Verify markdown formatting across API.md and ZOD.md
@kzndotsh kzndotsh merged commit 120b7a4 into main Feb 2, 2026
20 checks passed
kzndotsh added a commit that referenced this pull request Feb 2, 2026
Address PR #37 review comments from Amazon Q Developer and Sourcery AI:

- Add full validation to `nick` field in UpdateIrcAccountRequestSchema
  - Apply same trim, min, max, and refine rules as CreateIrcAccountRequestSchema
  - Prevents invalid nicks from passing schema validation

- Add full validation to `username` field in UpdateXmppAccountRequestSchema
  - Apply same trim, min, and refine rules as CreateXmppAccountRequestSchema
  - Prevents invalid usernames from passing schema validation

Both update schemas now enforce the same validation rules as their
corresponding create schemas, ensuring data integrity at the schema level
even though the implementation may reject certain updates.

Fixes: #37 (comment)
Fixes: #37 (comment)
github-actions bot pushed a commit that referenced this pull request Feb 2, 2026
# [1.4.0](v1.3.0...v1.4.0) (2026-02-02)

### Bug Fixes

* add validation to update schema fields per PR feedback ([3b7e318](3b7e318)), closes [#37](#37)
* address Cubic AI code review findings ([45e3071](45e3071))
* **deps:** align drizzle-zod version with drizzle-orm beta ([edf7a1e](edf7a1e))
* handle invalid JSON request body with a 400 API error. ([9e10870](9e10870))
* implement safe metadata parsing and refine linter config ([0e8888b](0e8888b))
* **integrations:** add UI validation guard to prevent empty payload ([7a17f85](7a17f85))

### Features

* **base.ts:** add support for schema validation using zod ([80a3e4a](80a3e4a))
* **core:** integrate zod-validation-error and enhance integration base types ([1ab3376](1ab3376))
* **hooks:** add generic input type parameters for integration account hooks ([2bc910a](2bc910a))
* Implement type-safe integration account creation and update using Zod schemas and branded types. ([4c176a1](4c176a1))
* **integrations:** implement type-safe forms and schema-backed routing ([b3fe80d](b3fe80d))
* Introduce new `react-hook-form-zod` and `zod` skills with various form templates and update integration schemas and documentation." ([c2eb2b9](c2eb2b9))
* **irc:** add account schema validation for IRC integration ([f982174](f982174))
* **schemas:** centralize user and admin validation schemas ([b2f9e69](b2f9e69))
* **types.ts:** add Zod schema types for account creation and update ([58b0326](58b0326))
* **utils.ts:** add brandedString helper function for creating branded string schemas ([50450da](50450da))
* **xmpp:** add CreateXmppAccountRequestSchema to XmppIntegration ([c399216](c399216))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: zod

1 participant