Conversation
- 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.
Reviewer's GuideRefactors 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 schemasequenceDiagram
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
Class diagram for updated IRC and XMPP integration schemas and typesclassDiagram
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
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughCentralizes 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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
Summary of ChangesHello @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 Highlights
Using Gemini Code AssistThe 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
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 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
|
Codecov Report❌ Patch coverage is 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. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
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-zodintegration 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
- 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(), |
There was a problem hiding this comment.
🛑 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.
| 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(), |
There was a problem hiding this comment.
🛑 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.
| 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(), |
There was a problem hiding this comment.
Hey - I've found 3 issues, and left some high level feedback:
- The new IRC/XMPP type aliases in
src/features/integrations/lib/*/types.tsnow duplicate the inferred types already exported fromsrc/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 introducedmetadataSchemainsrc/shared/schemas/utils.ts, it would be cleaner and more consistent to reuse that helper in these schemas. - For XMPP,
CreateXmppAccountRequestSchema.usernameincludesisValidXmppUsernamevalidation whileUpdateXmppAccountRequestSchema.usernameis a barez.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>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
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
jsonbfields 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.
| .transform((data) => ({ | ||
| ...data, | ||
| // Transform metadata from unknown to proper type | ||
| metadata: data.metadata as Record<string, unknown> | undefined, | ||
| })); |
There was a problem hiding this comment.
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.
| .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), | |
| })); |
| .transform((data) => ({ | ||
| ...data, | ||
| // Transform metadata from unknown to proper type | ||
| metadata: data.metadata as Record<string, unknown> | undefined, | ||
| })); |
There was a problem hiding this comment.
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.
| .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), | |
| })); |
| "linter": { | ||
| "rules": { | ||
| "performance": { | ||
| "noBarrelFile": "off", | ||
| "noNamespaceImport": "off" | ||
| } | ||
| } | ||
| }, |
There was a problem hiding this comment.
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).
| .transform((data) => ({ | ||
| ...data, | ||
| // Transform metadata from unknown to proper type | ||
| metadata: data.metadata as Record<string, unknown> | undefined, | ||
| })); |
There was a problem hiding this comment.
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.
| .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), | |
| })); |
There was a problem hiding this comment.
3 issues found across 25 files
Confidence score: 3/5
- Update schemas in
src/shared/schemas/integrations/irc.tsandsrc/shared/schemas/integrations/xmpp.tsare looser than create, allowing invalid nick/username values through update requests; this is a concrete user-facing data validation gap. src/shared/schemas/utils.tsmetadata 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.
There was a problem hiding this comment.
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 disablingnoBarrelFile(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 scopingnoNamespaceImportrelaxations.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 withcreateAccount.The
createAccountmethod (lines 54-58) extracts specific Zod validation messages, whileupdateAccountuses 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (24)
biome.jsoncdocs/ZOD.mdpackage.jsonsrc/app/(dashboard)/app/integrations/integrations-content.tsxsrc/app/metadata.tssrc/features/admin/api/index.tssrc/features/auth/lib/config.tssrc/features/integrations/api/index.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/irc/types.tssrc/features/integrations/lib/irc/unreal/client.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/xmpp/types.tssrc/features/user/api/index.tssrc/shared/api/index.tssrc/shared/db/schema/irc.tssrc/shared/db/schema/xmpp.tssrc/shared/schemas/index.tssrc/shared/schemas/integrations/index.tssrc/shared/schemas/integrations/irc.tssrc/shared/schemas/integrations/xmpp.tssrc/shared/schemas/utils.tssrc/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}: UseSentry.captureException(error)to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected
UseSentry.startSpan()function to create spans for meaningful actions within applications like button clicks, API calls, and function calls
Files:
src/shared/schemas/index.tssrc/shared/db/schema/xmpp.tssrc/shared/schemas/integrations/index.tssrc/shared/db/schema/irc.tssrc/shared/schemas/utils.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/xmpp.tssrc/features/integrations/lib/xmpp/types.tssrc/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 thenameandopproperties are meaningful (e.g.,op: "http.client"with descriptive names likeGET /api/users/${userId}), and attach attributes based on relevant request information and metrics
Files:
src/shared/schemas/index.tssrc/shared/db/schema/xmpp.tssrc/shared/schemas/integrations/index.tssrc/shared/db/schema/irc.tssrc/shared/schemas/utils.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/xmpp.tssrc/features/integrations/lib/xmpp/types.tssrc/features/integrations/lib/irc/types.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)
**/*.{js,ts,jsx,tsx}: Import Sentry usingimport * as Sentry from "@sentry/nextjs"when using logs in NextJS projects
Reference the Sentry logger usingconst { logger } = Sentrywhen using logging functionality
Uselogger.fmtas a template literal function to bring variables into structured logs, providing better log formatting and variable interpolation
Files:
src/shared/schemas/index.tssrc/shared/db/schema/xmpp.tssrc/shared/schemas/integrations/index.tssrc/shared/db/schema/irc.tssrc/shared/schemas/utils.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/xmpp.tssrc/features/integrations/lib/xmpp/types.tssrc/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.tssrc/shared/db/schema/xmpp.tssrc/shared/schemas/integrations/index.tssrc/shared/db/schema/irc.tssrc/shared/schemas/utils.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/xmpp.tssrc/features/integrations/lib/xmpp/types.tssrc/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-*, andperspective-origin-*
Use linear gradient angles withbg-linear-45syntax and gradient interpolation likebg-linear-to-r/oklchorbg-linear-to-r/srgb
Use conic and radial gradients withbg-conicandbg-radial-[at_25%_25%]utilities
Useinset-shadow-*andinset-ring-*utilities instead of deprecated shadow opacity utilities
Usefield-sizing-contentutility for auto-resizing textareas
Usescheme-lightandscheme-darkutilities forcolor-schemeproperty
Usefont-stretch-*utilities for variable font configuration
Chain variants together for composable variants (e.g.,group-has-data-potato:opacity-100)
Usestartingvariant for@starting-styletransitions
Usenot-*variant for:not()pseudo-class (e.g.,not-first:mb-4)
Useinertvariant for styling elements with theinertattribute
Usenth-*variants:nth-3:,nth-last-5:,nth-of-type-4:,nth-last-of-type-6:for targeting specific elements
Usein-*variant as a simpler alternative togroup-*without addinggroupclass
Useopenvariant to support:popover-openpseudo-class
Use**variant for targeting all descendants
Replace deprecatedbg-opacity-*utilities with color values using slash notation (e.g.,bg-black/50)
Replace deprecatedtext-opacity-*utilities with color values using slash notation (e.g.,text-black/50)
Replace deprecatedborder-opacity-*,divide-opacity-*and similar opacity utilities with color slash notation
Useshadow-xsinstead ofshadow-smandshadow-sminstead ofshadow
Usedrop-shadow-xsinstead ofdrop-shadow-smanddrop-shadow-sminstead ofdrop-shadow
Useblur-xsinstead ofblur-smandblur-sminstead ofblur
Userounded-xsinstead ofrounded-smandrounded-sminstead ofrounded
Useoutline-hiddeninstead ofoutline-nonefor...
Files:
src/shared/schemas/index.tssrc/shared/db/schema/xmpp.tssrc/shared/schemas/integrations/index.tssrc/shared/db/schema/irc.tssrc/shared/schemas/utils.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/xmpp.tssrc/features/integrations/lib/xmpp/types.tssrc/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
Preferunknownoveranywhen 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; preferunknownoverany
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@/authmodule using barrel exports
Import database operations from@/dbmodule using barrel exports
Import app configuration from@/configor@/config/appusing 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 insrc/types/directory: use@/types/auth,@/types/api,@/types/routes,@/types/email,@/types/commonfor 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.tssrc/shared/db/schema/xmpp.tssrc/shared/schemas/integrations/index.tssrc/shared/db/schema/irc.tssrc/shared/schemas/utils.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/xmpp.tssrc/features/integrations/lib/xmpp/types.tssrc/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
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax 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 thekeyprop 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
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks 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.tssrc/shared/db/schema/xmpp.tssrc/shared/schemas/integrations/index.tssrc/shared/db/schema/irc.tssrc/shared/schemas/utils.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/xmpp.tssrc/features/integrations/lib/xmpp/types.tssrc/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.tssrc/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.tssrc/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.tsbiome.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.tssrc/shared/schemas/integrations/index.tssrc/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.tsdocs/ZOD.mdsrc/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.tssrc/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.tsdocs/ZOD.mdsrc/shared/schemas/utils.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/xmpp.tssrc/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.mdsrc/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.tssrc/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’screateSelectSchema/createInsertSchemasignatures 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’screateSelectSchema/createInsertSchemasignatures 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 inoptionalNonEmptyStringSchemabehaves 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
@/authand@/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.
…chemas for IRC and XMPP.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 globalnoNamespaceImportdisable or drop the rule.Disabling it for all
**/*.tsand**/*.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 scopednoBarrelFileexceptions, 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
📒 Files selected for processing (7)
biome.jsoncdocs/ZOD.mdsrc/features/integrations/lib/irc/types.tssrc/features/integrations/lib/xmpp/types.tssrc/shared/schemas/integrations/irc.tssrc/shared/schemas/integrations/xmpp.tssrc/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}: UseSentry.captureException(error)to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected
UseSentry.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.tssrc/shared/schemas/integrations/irc.tssrc/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 thenameandopproperties are meaningful (e.g.,op: "http.client"with descriptive names likeGET /api/users/${userId}), and attach attributes based on relevant request information and metrics
Files:
src/features/integrations/lib/xmpp/types.tssrc/shared/schemas/integrations/irc.tssrc/shared/schemas/integrations/xmpp.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)
**/*.{js,ts,jsx,tsx}: Import Sentry usingimport * as Sentry from "@sentry/nextjs"when using logs in NextJS projects
Reference the Sentry logger usingconst { logger } = Sentrywhen using logging functionality
Uselogger.fmtas a template literal function to bring variables into structured logs, providing better log formatting and variable interpolation
Files:
src/features/integrations/lib/xmpp/types.tssrc/shared/schemas/integrations/irc.tssrc/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.tssrc/shared/schemas/integrations/irc.tssrc/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-*, andperspective-origin-*
Use linear gradient angles withbg-linear-45syntax and gradient interpolation likebg-linear-to-r/oklchorbg-linear-to-r/srgb
Use conic and radial gradients withbg-conicandbg-radial-[at_25%_25%]utilities
Useinset-shadow-*andinset-ring-*utilities instead of deprecated shadow opacity utilities
Usefield-sizing-contentutility for auto-resizing textareas
Usescheme-lightandscheme-darkutilities forcolor-schemeproperty
Usefont-stretch-*utilities for variable font configuration
Chain variants together for composable variants (e.g.,group-has-data-potato:opacity-100)
Usestartingvariant for@starting-styletransitions
Usenot-*variant for:not()pseudo-class (e.g.,not-first:mb-4)
Useinertvariant for styling elements with theinertattribute
Usenth-*variants:nth-3:,nth-last-5:,nth-of-type-4:,nth-last-of-type-6:for targeting specific elements
Usein-*variant as a simpler alternative togroup-*without addinggroupclass
Useopenvariant to support:popover-openpseudo-class
Use**variant for targeting all descendants
Replace deprecatedbg-opacity-*utilities with color values using slash notation (e.g.,bg-black/50)
Replace deprecatedtext-opacity-*utilities with color values using slash notation (e.g.,text-black/50)
Replace deprecatedborder-opacity-*,divide-opacity-*and similar opacity utilities with color slash notation
Useshadow-xsinstead ofshadow-smandshadow-sminstead ofshadow
Usedrop-shadow-xsinstead ofdrop-shadow-smanddrop-shadow-sminstead ofdrop-shadow
Useblur-xsinstead ofblur-smandblur-sminstead ofblur
Userounded-xsinstead ofrounded-smandrounded-sminstead ofrounded
Useoutline-hiddeninstead ofoutline-nonefor...
Files:
src/features/integrations/lib/xmpp/types.tssrc/shared/schemas/integrations/irc.tssrc/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
Preferunknownoveranywhen 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; preferunknownoverany
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@/authmodule using barrel exports
Import database operations from@/dbmodule using barrel exports
Import app configuration from@/configor@/config/appusing 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 insrc/types/directory: use@/types/auth,@/types/api,@/types/routes,@/types/email,@/types/commonfor 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.tssrc/shared/schemas/integrations/irc.tssrc/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
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax 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 thekeyprop 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
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks 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.tssrc/shared/schemas/integrations/irc.tssrc/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.tssrc/shared/schemas/integrations/xmpp.tsdocs/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.tsdocs/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.
… Irc account schemas.
…metadata transformation.
…us form templates and update integration schemas and documentation."
…ng Zod schemas and branded types.
…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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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: Unusedupdatedestructured fromuseFieldArray.The
updatefunction 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: Missingdisabledcheck 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:
- 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.- Error displays for all validated fields —
levelandyearsOfExperiencehave Zod validation but no corresponding error message rendering.Compare with
DynamicContactListwhich 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
BasicSignupFormlacks the accessibility attributes present inBasicLoginForm:
- Missing
aria-invalidon inputs- Missing
aria-describedbylinking inputs to error messages- Error spans missing
idattributesSince 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:
- Tables (Lines 41, 117, 125): Add spaces around pipe characters for consistent "compact" style
- Code fences (Lines 103, 135): Add language specifiers (e.g.,
textorbash)- 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):
-``` +```textFor 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/idassociations. 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: Replaceanywithunknownfor error type.Per coding guidelines, prefer
unknownoveranywhen 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: AlignsettingsFormSchema.languagewith the actual fields.
languageis 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
📒 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.mddocs/ZOD.mdsrc/app/api/integrations/[integration]/accounts/route.tssrc/features/integrations/api/integrations.tssrc/features/integrations/hooks/use-integration.tssrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/integrations/irc.tssrc/shared/schemas/integrations/xmpp.tssrc/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}: UseSentry.captureException(error)to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected
UseSentry.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.tssrc/app/api/integrations/[integration]/accounts/route.tssrc/shared/schemas/utils.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/api/integrations.tssrc/shared/schemas/integrations/irc.tssrc/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 thenameandopproperties are meaningful (e.g.,op: "http.client"with descriptive names likeGET /api/users/${userId}), and attach attributes based on relevant request information and metrics
Files:
src/features/integrations/lib/core/types.tssrc/app/api/integrations/[integration]/accounts/route.tssrc/shared/schemas/utils.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/api/integrations.tssrc/shared/schemas/integrations/irc.tssrc/features/integrations/hooks/use-integration.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)
**/*.{js,ts,jsx,tsx}: Import Sentry usingimport * as Sentry from "@sentry/nextjs"when using logs in NextJS projects
Reference the Sentry logger usingconst { logger } = Sentrywhen using logging functionality
Uselogger.fmtas a template literal function to bring variables into structured logs, providing better log formatting and variable interpolation
Files:
src/features/integrations/lib/core/types.tssrc/app/api/integrations/[integration]/accounts/route.tssrc/shared/schemas/utils.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/api/integrations.tssrc/shared/schemas/integrations/irc.tssrc/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.tssrc/app/api/integrations/[integration]/accounts/route.tssrc/shared/schemas/utils.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/api/integrations.tssrc/shared/schemas/integrations/irc.tssrc/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-*, andperspective-origin-*
Use linear gradient angles withbg-linear-45syntax and gradient interpolation likebg-linear-to-r/oklchorbg-linear-to-r/srgb
Use conic and radial gradients withbg-conicandbg-radial-[at_25%_25%]utilities
Useinset-shadow-*andinset-ring-*utilities instead of deprecated shadow opacity utilities
Usefield-sizing-contentutility for auto-resizing textareas
Usescheme-lightandscheme-darkutilities forcolor-schemeproperty
Usefont-stretch-*utilities for variable font configuration
Chain variants together for composable variants (e.g.,group-has-data-potato:opacity-100)
Usestartingvariant for@starting-styletransitions
Usenot-*variant for:not()pseudo-class (e.g.,not-first:mb-4)
Useinertvariant for styling elements with theinertattribute
Usenth-*variants:nth-3:,nth-last-5:,nth-of-type-4:,nth-last-of-type-6:for targeting specific elements
Usein-*variant as a simpler alternative togroup-*without addinggroupclass
Useopenvariant to support:popover-openpseudo-class
Use**variant for targeting all descendants
Replace deprecatedbg-opacity-*utilities with color values using slash notation (e.g.,bg-black/50)
Replace deprecatedtext-opacity-*utilities with color values using slash notation (e.g.,text-black/50)
Replace deprecatedborder-opacity-*,divide-opacity-*and similar opacity utilities with color slash notation
Useshadow-xsinstead ofshadow-smandshadow-sminstead ofshadow
Usedrop-shadow-xsinstead ofdrop-shadow-smanddrop-shadow-sminstead ofdrop-shadow
Useblur-xsinstead ofblur-smandblur-sminstead ofblur
Userounded-xsinstead ofrounded-smandrounded-sminstead ofrounded
Useoutline-hiddeninstead ofoutline-nonefor...
Files:
src/features/integrations/lib/core/types.tssrc/app/api/integrations/[integration]/accounts/route.tssrc/shared/schemas/utils.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/api/integrations.tssrc/shared/schemas/integrations/irc.tssrc/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
Preferunknownoveranywhen 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; preferunknownoverany
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@/authmodule using barrel exports
Import database operations from@/dbmodule using barrel exports
Import app configuration from@/configor@/config/appusing 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 insrc/types/directory: use@/types/auth,@/types/api,@/types/routes,@/types/email,@/types/commonfor 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.tssrc/app/api/integrations/[integration]/accounts/route.tssrc/shared/schemas/utils.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/api/integrations.tssrc/shared/schemas/integrations/irc.tssrc/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
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax 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 thekeyprop 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
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks 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.tssrc/app/api/integrations/[integration]/accounts/route.tssrc/shared/schemas/utils.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/api/integrations.tssrc/shared/schemas/integrations/irc.tssrc/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.mdsrc/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.tsxsrc/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.tsxsrc/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.tsxsrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/irc/implementation.ts.cursor/skills/react-hook-form-zod/templates/server-validation.tssrc/shared/schemas/integrations/irc.tsdocs/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.mdsrc/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.tsxsrc/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.tsxsrc/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.tsxsrc/features/integrations/lib/core/base.ts.cursor/skills/react-hook-form-zod/templates/server-validation.tssrc/shared/schemas/integrations/irc.tsdocs/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.tssrc/shared/schemas/utils.tsdocs/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.tssrc/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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 | 🟡 MinorMinor: Textarea not cleaned up if
execCommandfails.If
execCommand("copy")returns false (line 108), the error is thrown beforeremoveChild(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 increateAccount.Unlike the IRC implementation which uses
CreateIrcAccountRequestSchema.safeParse(input)at the method entry, the XMPPcreateAccountrelies ondetermineUsernamefor 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 aZodErrorif 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
safeParsefor defensive output validation to avoid 500 errors on schema mismatches.src/features/integrations/components/integration-management.tsx (3)
47-48: Consider adding@deprecatedJSDoc annotation.The
createInputRequiredprop 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 inonSubmit, but this loses the connection to the schema's expected shape. While theanycast 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 addingaria-describedbyfor 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
#6mentions handling JSONB fields with.transform()andmetadataSchema.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
banExpiresfield transforms any string to aDate, but invalid date strings will produceInvalid 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 countFor 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (17)
docs/API.mddocs/INTEGRATIONS.mddocs/ZOD.mdpackage.jsonsrc/app/(dashboard)/app/integrations/integrations-content.tsxsrc/app/api/admin/users/[id]/route.tssrc/app/api/admin/users/route.tssrc/app/api/integrations/[integration]/accounts/route.tssrc/app/api/user/me/route.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/base.tssrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/features/integrations/lib/xmpp/implementation.tssrc/shared/api/utils.tssrc/shared/schemas/index.tssrc/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}: UseSentry.captureException(error)to capture exceptions and log errors in Sentry, particularly in try-catch blocks or areas where exceptions are expected
UseSentry.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.tssrc/features/integrations/lib/xmpp/implementation.tssrc/app/api/admin/users/route.tssrc/shared/schemas/user.tssrc/features/integrations/lib/core/base.tssrc/app/api/admin/users/[id]/route.tssrc/shared/api/utils.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/app/api/user/me/route.tssrc/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 thenameandopproperties are meaningful (e.g.,op: "http.client"with descriptive names likeGET /api/users/${userId}), and attach attributes based on relevant request information and metrics
Files:
src/app/api/integrations/[integration]/accounts/route.tssrc/features/integrations/lib/xmpp/implementation.tssrc/app/api/admin/users/route.tssrc/shared/schemas/user.tssrc/features/integrations/lib/core/base.tssrc/app/api/admin/users/[id]/route.tssrc/shared/api/utils.tssrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/app/api/user/me/route.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/sentry.mdc)
**/*.{js,ts,jsx,tsx}: Import Sentry usingimport * as Sentry from "@sentry/nextjs"when using logs in NextJS projects
Reference the Sentry logger usingconst { logger } = Sentrywhen using logging functionality
Uselogger.fmtas 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.tssrc/features/integrations/lib/xmpp/implementation.tssrc/app/api/admin/users/route.tssrc/shared/schemas/user.tssrc/features/integrations/lib/core/base.tssrc/app/api/admin/users/[id]/route.tssrc/shared/api/utils.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/app/api/user/me/route.tssrc/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.tssrc/features/integrations/lib/xmpp/implementation.tssrc/app/api/admin/users/route.tssrc/shared/schemas/user.tssrc/features/integrations/lib/core/base.tssrc/app/api/admin/users/[id]/route.tssrc/shared/api/utils.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/app/api/user/me/route.tssrc/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-*, andperspective-origin-*
Use linear gradient angles withbg-linear-45syntax and gradient interpolation likebg-linear-to-r/oklchorbg-linear-to-r/srgb
Use conic and radial gradients withbg-conicandbg-radial-[at_25%_25%]utilities
Useinset-shadow-*andinset-ring-*utilities instead of deprecated shadow opacity utilities
Usefield-sizing-contentutility for auto-resizing textareas
Usescheme-lightandscheme-darkutilities forcolor-schemeproperty
Usefont-stretch-*utilities for variable font configuration
Chain variants together for composable variants (e.g.,group-has-data-potato:opacity-100)
Usestartingvariant for@starting-styletransitions
Usenot-*variant for:not()pseudo-class (e.g.,not-first:mb-4)
Useinertvariant for styling elements with theinertattribute
Usenth-*variants:nth-3:,nth-last-5:,nth-of-type-4:,nth-last-of-type-6:for targeting specific elements
Usein-*variant as a simpler alternative togroup-*without addinggroupclass
Useopenvariant to support:popover-openpseudo-class
Use**variant for targeting all descendants
Replace deprecatedbg-opacity-*utilities with color values using slash notation (e.g.,bg-black/50)
Replace deprecatedtext-opacity-*utilities with color values using slash notation (e.g.,text-black/50)
Replace deprecatedborder-opacity-*,divide-opacity-*and similar opacity utilities with color slash notation
Useshadow-xsinstead ofshadow-smandshadow-sminstead ofshadow
Usedrop-shadow-xsinstead ofdrop-shadow-smanddrop-shadow-sminstead ofdrop-shadow
Useblur-xsinstead ofblur-smandblur-sminstead ofblur
Userounded-xsinstead ofrounded-smandrounded-sminstead ofrounded
Useoutline-hiddeninstead ofoutline-nonefor...
Files:
src/app/api/integrations/[integration]/accounts/route.tssrc/features/integrations/lib/xmpp/implementation.tssrc/app/api/admin/users/route.tssrc/shared/schemas/user.tssrc/features/integrations/lib/core/base.tssrc/app/api/admin/users/[id]/route.tssrc/shared/api/utils.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/app/api/user/me/route.tssrc/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
Preferunknownoveranywhen 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; preferunknownoverany
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@/authmodule using barrel exports
Import database operations from@/dbmodule using barrel exports
Import app configuration from@/configor@/config/appusing 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 insrc/types/directory: use@/types/auth,@/types/api,@/types/routes,@/types/email,@/types/commonfor 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.tssrc/features/integrations/lib/xmpp/implementation.tssrc/app/api/admin/users/route.tssrc/shared/schemas/user.tssrc/features/integrations/lib/core/base.tssrc/app/api/admin/users/[id]/route.tssrc/shared/api/utils.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/app/api/user/me/route.tssrc/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.tssrc/app/api/admin/users/route.tssrc/app/api/admin/users/[id]/route.tssrc/app/api/user/me/route.tssrc/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
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax 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 thekeyprop 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
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks 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.tssrc/features/integrations/lib/xmpp/implementation.tssrc/app/api/admin/users/route.tssrc/shared/schemas/user.tssrc/features/integrations/lib/core/base.tssrc/app/api/admin/users/[id]/route.tssrc/shared/api/utils.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/types.tssrc/features/integrations/lib/irc/implementation.tssrc/app/api/user/me/route.tssrc/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.tssrc/app/api/admin/users/route.tssrc/app/api/admin/users/[id]/route.tssrc/app/api/user/me/route.tssrc/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 thenameandopproperties are meaningful for the activities in the call, and attach attributes based on relevant information and metrics
Files:
src/features/integrations/components/integration-management.tsxsrc/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.mdsrc/features/integrations/lib/xmpp/implementation.tssrc/shared/schemas/user.tssrc/features/integrations/lib/core/base.tsdocs/ZOD.mdsrc/shared/api/utils.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/types.tssrc/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.mdsrc/app/api/integrations/[integration]/accounts/route.tssrc/features/integrations/lib/xmpp/implementation.tssrc/features/integrations/lib/core/base.tsdocs/ZOD.mdsrc/shared/api/utils.tssrc/features/integrations/components/integration-management.tsxsrc/features/integrations/lib/core/types.tssrc/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.mdsrc/shared/schemas/user.tssrc/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.mdsrc/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.mdsrc/shared/schemas/user.tssrc/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.mdsrc/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.mdsrc/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.tssrc/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.tssrc/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.tssrc/app/api/admin/users/route.tssrc/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.tssrc/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.tssrc/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.tssrc/shared/schemas/user.tssrc/app/api/admin/users/[id]/route.tssrc/features/integrations/components/integration-management.tsxsrc/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.tssrc/shared/schemas/user.tssrc/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.tssrc/app/api/admin/users/[id]/route.tssrc/features/integrations/lib/irc/implementation.tssrc/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.tssrc/features/integrations/components/integration-management.tsxsrc/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.tsxsrc/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.tsxsrc/features/integrations/lib/irc/implementation.tssrc/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.tsxsrc/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.tsxsrc/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.tssrc/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 sincez.ZodTypeis 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
IntegrationBaseOptionscorrectly introduces generic parameters for schema types. Usingz.ZodType<unknown>foraccountSchemais a reasonable trade-off sinceTAccountisn'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/ircand constructor wiring are correct. The double cast onaccountSchema(lines 42-44) is necessary becauseIrcAccountSchemadoesn't inherently include the optionaltemporaryPasswordfield 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
safeParsewith 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
accountSchemais simpler here sinceXmppAccountdoesn'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
safeParsewith 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 wherenickis the required field.Also applies to: 154-157
282-285: LGTM! Clean schema-driven integration for XMPP.Same pattern as IRC -
createInputName="username"matches theusernamefield inCreateXmppAccountRequestSchema.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-zodto 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-errorfor user-friendly error messages- Client-Side Form Validation (lines 398-409): Standardizes on
react-hook-formwithzodResolver, 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:
- Add drizzle-zod schema generation
- Create custom validation schemas by extending base schemas
- Replace manual interfaces with
z.infertypes- 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. ThebrandedStringhelper is correctly exported from@/shared/schemas/utils(defined at line 52-53 ofsrc/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-zodfor schema generation andzod-validation-errorfor 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.issuesindetailsprovides 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
handleAPIErrorto catch and format Zod validation errorsThis 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
nameandimagefields 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.
src/features/integrations/components/integration-management.tsx
Outdated
Show resolved
Hide resolved
- 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
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)
# [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))
Description
Changes
Type of Change
Testing
Test Steps
Checklist
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:
Build:
Documentation: