Ctrl K
ComunidadGuías…

AGENTS.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Worklenz Cursor Rules for AI Assistants

## 🎯 Project Overview
Worklenz is a full-stack project management application with React frontend, Node.js/Express backend, and PostgreSQL database. This document provides cursor rules for AI assistants working on this codebase.

## 📋 General Development Rules

### 🎨 UI/UX Guidelines
- **Always consider dark/light theme compatibility** when creating or modifying UI components
- **No hardcoded text** - all user-facing strings must use i18next localization
- **Follow Ant Design patterns** - use existing components and design tokens consistently
- **Responsive design** - ensure components work on mobile, tablet, and desktop
- **Accessibility first** - include proper ARIA labels, keyboard navigation, and screen reader support

### 🔧 Code Quality Standards
- **TypeScript strict mode** - use strict typing, avoid `any` types
- **Functional programming** - prefer functional patterns over classes
- **Descriptive naming** - use auxiliary verbs (e.g., `isLoading`, `hasError`, `canEdit`)
- **Modular structure** - break down complex components into smaller, reusable pieces
- **Performance conscious** - use React.memo, useMemo, useCallback appropriately

### 📁 File Organization
```
# Component file structure pattern
export const MainComponent = () => { /* main component */ };

const SubComponent = () => { /* subcomponent */ };
const AnotherSubComponent = () => { /* another subcomponent */ };

// Helper functions
const formatData = (data: DataType) => { /* helper logic */ };
const validateInput = (input: string) => { /* validation logic */ };

// Static content
const DEFAULT_CONFIG = { /* static configuration */ };
const ERROR_MESSAGES = { /* error messages */ };

// Types and interfaces
interface ComponentProps {
  data: DataType;
  onSubmit: (value: string) => void;
}
```

## 🚀 Frontend-Specific Rules

### React/TypeScript Patterns
- **Prefer interfaces over types** for object shapes
- **Use custom hooks** for reusable logic (auth, API calls, socket connections)
- **Implement error boundaries** for graceful error handling
- **Follow Redux Toolkit patterns** for state management
- **Use React 18 features** (Suspense, concurrent rendering)

### Component Development
```typescript
// ✅ Preferred: Named export with proper typing
interface TaskCardProps {
  task: IProjectTask;
  onUpdate: (taskId: string, updates: Partial<IProjectTask>) => void;
  isSelected?: boolean;
}

export const TaskCard: React.FC<TaskCardProps> = ({
  task,
  onUpdate,
  isSelected = false
}) => {
  // Component logic
};

// ❌ Avoid: Default export, unnecessary React.FC
const TaskCard = (props: any) => {
  // Component logic
};
export default TaskCard;
```

### State Management
- **Use Redux Toolkit** for global state management
- **Feature-based organization** - group related actions, reducers, selectors
- **Typed selectors** with proper error handling
- **Optimistic updates** for better UX, with rollback on failure

### API Integration
- **RTK Query for server state** - use existing API services pattern
- **Proper error handling** - use try/catch with user-friendly error messages
- **Loading states** - always show loading indicators for async operations
- **Cache management** - invalidate cache appropriately on mutations

## 🏗️ Backend-Specific Rules

### Express.js Patterns
- **MVC structure** - controllers handle business logic, routes define endpoints
- **Middleware chain** - authentication, validation, error handling
- **Consistent response format** - use established response patterns
- **Input validation** - validate all inputs, never trust client data

### Database Operations
- **Use transactions** for multi-table operations
- **Prepared statements** - prevent SQL injection
- **Proper indexing** - consider query performance
- **Migration safety** - ensure migrations are reversible
- **Primary keys must be UUIDs** - use `UUID` for table PK columns, not serial/integer IDs
- **UUID default generation** - define PK defaults as `uuid_generate_v4()` (ensure `uuid-ossp` extension is available in migrations)

### Socket.IO Implementation
- **Namespace organization** - use appropriate namespaces for different features
- **Event naming** - consistent, descriptive event names
- **Error handling** - handle socket errors gracefully
- **Connection management** - handle disconnects and reconnections

## 🔄 Real-time Features

### WebSocket Events
- **Consistent event naming** - use established patterns
- **Proper typing** - type all event payloads
- **Error handling** - handle connection failures
- **Performance** - avoid sending unnecessary updates

### Collaboration Features
- **Optimistic updates** - update UI immediately, rollback on failure
- **Conflict resolution** - handle concurrent modifications
- **User feedback** - show who made changes and when

## 🎨 Styling Guidelines

### Tailwind CSS Usage
- **Utility-first approach** - use Tailwind classes primarily
- **Consistent spacing** - use established spacing scale
- **Dark mode support** - test all components in both themes
- **Responsive design** - use responsive utilities appropriately

### Ant Design Integration
- **Follow design tokens** - use theme variables, not hardcoded colors
- **Consistent component usage** - use established component patterns
- **Custom styling** - extend rather than override Ant Design styles
- **Theme awareness** - respect user's theme preference

## 📝 Localization Rules

### i18next Integration
- **No hardcoded strings** - all user text must be localized
- **Always include defaultValue** - every `t()` call must include a `defaultValue` parameter for fallback text
  - Example: `t('taskNameColumn', { defaultValue: 'Task' })`
  - This ensures graceful degradation when translation keys are missing
- **Namespace organization** - group related strings by feature
- **Pluralization support** - use i18next pluralization features
- **Interpolation** - use variables safely with proper escaping

### Translation Structure
```
public/locales/en/
├── common.json          # Shared strings
├── auth.json           # Authentication
├── tasks.json          # Task management
├── projects.json       # Project management
└── settings.json       # User settings
```

## 🧪 Testing Guidelines

### Component Testing
- **React Testing Library** for component testing
- **User-centric testing** - test user interactions, not implementation details
- **Accessibility testing** - include a11y checks
- **Visual regression** - test component appearance

### API Testing
- **Integration tests** for API endpoints
- **Database isolation** - use test database or transactions
- **Authentication testing** - test protected routes
- **Error scenarios** - test error conditions and edge cases

## 🚀 Performance Optimization

### Frontend Performance
- **Code splitting** - use dynamic imports for large components
- **Virtualization** - for large lists (react-window)
- **Image optimization** - use appropriate formats and sizes
- **Bundle analysis** - monitor bundle size and dependencies

### Backend Performance
- **Database optimization** - use proper indexes and query optimization
- **Caching strategy** - implement appropriate caching layers
- **Rate limiting** - protect against abuse
- **Monitoring** - implement performance monitoring

## 🔒 Security Guidelines

### Frontend Security
- **XSS prevention** - sanitize user input, use React's built-in protection
- **CSRF protection** - use established CSRF tokens
- **Secure storage** - never store sensitive data in localStorage
- **Input validation** - validate all user inputs

### Backend Security
- **Authentication** - use established auth patterns
- **Authorization** - check permissions on all protected routes
- **Data validation** - validate and sanitize all inputs
- **SQL injection prevention** - use prepared statements

## � Authentication & Security Configuration

### CSRF Protection

Worklenz uses CSRF (Cross-Site Request Forgery) protection for the main application API routes.

#### Backend Configuration

**Location**: `worklenz-backend/src/app.ts`

```typescript
// CSRF protection is applied to /api/v1 routes
app.use("/api/v1", apiLimiter, isLoggedIn, apiRouter);

// Client portal routes are EXCLUDED from CSRF protection
app.use("/api/client-portal", apiLimiter, clientPortalApiRouter);
```

**CSRF Exclusion Middleware**:
```typescript
app.use((req, res, next) => {
  // Exclude client portal endpoints (they use client token authentication)
  if (req.path.startsWith("/client-portal") || req.originalUrl.startsWith("/api/client-portal")) {
    return next();
  }
  
  // Apply CSRF protection to state-changing operations
  const isStateChanging = ['POST', 'PUT', 'DELETE', 'PATCH'].includes(req.method);
  if (isStateChanging) {
    csrfSynchronisedProtection(req, res, next);
  } else {
    next();
  }
});
```

#### Frontend Configuration (Main App)

**Location**: `worklenz-frontend/src/api/api-client.ts`

```typescript
// CSRF token management
export const getCsrfToken = (): string | null => {
  return localStorage.getItem('csrfToken');
};

export const refreshCsrfToken = async (): Promise<string> => {
  // Fetch new CSRF token from backend
  const response = await fetch('/api/v1/csrf-token');
  const { token } = await response.json();
  localStorage.setItem('csrfToken', token);
  return token;
};

// RTK Query configuration with CSRF
prepareHeaders: async headers => {
  let token = getCsrfToken();
  if (!token) {
    token = await refreshCsrfToken();
  }
  if (token) {
    headers.set('X-CSRF-Token', token);
  }
  return headers;
}
```

**Key Points**:
- CSRF tokens are stored in `localStorage`
- Tokens are automatically refreshed when missing
- All state-changing requests include `X-CSRF-Token` header
- CSRF protection applies to `/api/v1/*` routes only

### Client Portal Authentication

The Client Portal uses a **separate authentication mechanism** with client-specific tokens.

#### Two Frontend Applications

1. **Main Admin App** (`worklenz-frontend`)
   - For organization/admin users
   - Uses session-based auth + CSRF tokens
   - Manages client portal data from admin perspective
   - Base URL: `/api/v1` or `/api` (depending on API)

2. **Client Portal App** (`worklenz-client-portal`)
   - For client users
   - Uses `x-client-token` authentication
   - Direct client access to their data
   - Base URL: `/api/client-portal`

#### Client Portal Backend Routes

**Location**: `worklenz-backend/src/routes/apis/client-portal-api-router.ts`

```typescript
const router = express.Router();

// Public routes (no authentication)
router.post("/auth/login", safeControllerFunction(ClientPortalAuthController.clientLogin));
router.get("/invitation/validate", safeControllerFunction(ClientPortalAuthController.validateInvitation));

// Protected routes (require client authentication)
router.use(authenticateClient);

router.get("/dashboard", safeControllerFunction(ClientPortalDashboardController.getDashboard));
router.get("/invoices", safeControllerFunction(ClientPortalInvoicesController.getInvoices));
router.post("/invoices", safeControllerFunction(ClientPortalInvoicesController.createInvoice));
router.delete("/invoices/:id", safeControllerFunction(ClientPortalInvoicesController.deleteInvoice));
// ... more routes
```

#### Client Authentication Middleware

**Location**: `worklenz-backend/src/middlewares/client-auth-middleware.ts`

```typescript
export const authenticateClient = async (
  req: AuthenticatedClientRequest,
  res: Response,
  next: NextFunction
) => {
  // Get client token from headers or query params
  const clientToken = req.headers["x-client-token"] || req.query.clientToken;

  if (!clientToken) {
    return res.status(401).json(
      new ServerResponse(false, null, "Client token is required")
    );
  }

  // Verify client token
  const tokenPayload = TokenService.verifyClientToken(clientToken as string);
  
  if (!tokenPayload) {
    return res.status(401).json(
      new ServerResponse(false, null, "Invalid or expired client token")
    );
  }

  // Attach client info to request
  req.clientId = tokenPayload.clientId;
  req.organizationId = tokenPayload.organizationId;
  next();
};
```

#### Client Portal Frontend Configuration

**For Client Portal App** (`worklenz-client-portal/src/store/api.ts`):

```typescript
export const api = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl: '/api/client-portal',
    prepareHeaders: (headers) => {
      const token = localStorage.getItem('clientToken');
      if (token) {
        headers.set('x-client-token', token);
      }
      return headers;
    },
  }),
});
```

**For Admin App** (`worklenz-frontend/src/api/client-portal/client-portal-api.ts`):

```typescript
export const clientPortalApi = createApi({
  reducerPath: 'clientPortalApi',
  baseQuery: fetchBaseQuery({
    baseUrl: `${config.apiUrl}${API_BASE_URL}`,  // /api/v1
    prepareHeaders: async headers => {
      // Admin app uses CSRF tokens
      let token = getCsrfToken();
      if (!token) {
        token = await refreshCsrfToken();
      }
      if (token) {
        headers.set('X-CSRF-Token', token);
      }
      return headers;
    },
    credentials: 'include',
  }),
  endpoints: builder => ({
    // Endpoints use /clients/portal/* paths for admin management
    getInvoices: builder.query({
      query: () => '/clients/portal/invoices',  // Becomes /api/v1/clients/portal/invoices
    }),
  }),
});
```

### API Path Configuration Summary

| Frontend App | Base URL | Auth Method | Backend Route | Example Full URL |
|--------------|----------|-------------|---------------|------------------|
| Main Admin | `/api/v1` | CSRF Token + Session | `/api/v1/*` | `/api/v1/projects` |
| Admin (Client Portal Mgmt) | `/api/v1` | CSRF Token + Session | `/api/v1/clients/portal/*` | `/api/v1/clients/portal/invoices` |
| Client Portal App | `/api/client-portal` | x-client-token | `/api/client-portal/*` | `/api/client-portal/dashboard` |

### Common Authentication Issues

#### Issue: 401 Unauthorized on Client Portal Routes

**Cause**: Missing or invalid `x-client-token` header

**Solution**:
```typescript
// Ensure token is stored after login
localStorage.setItem('clientToken', token);

// Ensure token is sent in requests
headers.set('x-client-token', localStorage.getItem('clientToken'));
```

#### Issue: 404 Not Found on API Calls

**Cause**: Incorrect base URL or endpoint path configuration

**Solution**:
- **Admin managing client portal**: Use base URL `/api/v1` with endpoint paths `/clients/portal/*`
  - Example: `/api/v1/clients/portal/invoices`
- **Client portal app**: Use base URL `/api/client-portal` with endpoint paths starting with `/`
  - Example: `/api/client-portal/dashboard`
- **Main admin app**: Use base URL `/api/v1` with standard paths
  - Example: `/api/v1/projects`

#### Issue: CSRF Token Mismatch

**Cause**: Client portal routes receiving CSRF protection

**Solution**: Ensure client portal routes are excluded in `app.ts`:
```typescript
if (req.path.startsWith("/client-portal") || req.originalUrl.startsWith("/api/client-portal")) {
  return next(); // Skip CSRF protection
}
```

### Security Best Practices

1. **Never mix authentication methods**
   - Main app routes: Use CSRF tokens
   - Client portal routes: Use x-client-token
   - Don't apply CSRF to client portal routes

2. **Token storage**
   - CSRF tokens: `localStorage.getItem('csrfToken')`
   - Client tokens: `localStorage.getItem('clientToken')`
   - Never expose tokens in URLs or logs

3. **Route organization**
   - Client-facing portal routes: `/api/client-portal/*` (uses x-client-token)
   - Admin portal management routes: `/api/v1/clients/portal/*` (uses session + CSRF)
   - Main app routes: `/api/v1/*` (uses session + CSRF)
   - Use clear separation in route files

4. **Error handling**
   - Return 401 for authentication failures
   - Return 403 for authorization failures
   - Provide clear error messages for debugging

## �📚 Documentation Standards

### Code Documentation
- **JSDoc comments** for complex functions and components
- **Interface documentation** - document props and return types
- **Usage examples** - provide examples for complex APIs
- **README updates** - update documentation for significant changes

### API Documentation
- **OpenAPI/Swagger** for API endpoints
- **Request/response examples** - provide clear examples
- **Error responses** - document error conditions
- **Authentication** - document auth requirements

## 🔧 Development Workflow

### Git Practices
- **Feature branches** - create branches for new features
- **Descriptive commits** - write clear, concise commit messages
- **Code review** - follow established review process
- **Testing** - ensure tests pass before merging

### Code Review Checklist
- [ ] TypeScript types are correct and complete
- [ ] Component follows established patterns
- [ ] No hardcoded strings (i18n used)
- [ ] Dark/light theme compatibility
- [ ] Responsive design implemented
- [ ] Tests included for new functionality
- [ ] Performance considerations addressed
- [ ] Security implications reviewed

## 🎯 Task-Specific Rules

### New Feature Development
1. **Understand requirements** - clarify acceptance criteria
2. **Explore existing code** - find similar patterns to follow
3. **Plan implementation** - consider all affected components
4. **Implement incrementally** - build and test small pieces
5. **Add tests** - ensure new functionality is tested
6. **Update documentation** - document any API changes

### Bug Fixes
1. **Reproduce the issue** - understand the problem
2. **Identify root cause** - trace through the code
3. **Fix the issue** - implement the minimal fix
4. **Add regression test** - prevent future occurrences
5. **Verify fix** - test in multiple scenarios

### Refactoring
1. **Understand impact** - identify all affected code
2. **Plan incrementally** - avoid large breaking changes
3. **Maintain tests** - ensure tests still pass
4. **Update types** - keep TypeScript definitions current
5. **Document changes** - explain the refactoring rationale

---

## 🚨 Critical Rules

### Never Do These Things:
- ❌ **Hardcode user-facing text** - always use i18next
- ❌ **Use `any` type** - maintain strict TypeScript typing
- ❌ **Ignore theme compatibility** - all UI must support dark/light modes
- ❌ **Skip error handling** - always handle errors gracefully
- ❌ **Break existing API contracts** - maintain backward compatibility
- ❌ **Ignore accessibility** - all features must be accessible
- ❌ **Skip testing** - all features must be tested

### Always Do These Things:
- ✅ **Follow established patterns** - maintain consistency
- ✅ **Add proper TypeScript types** - ensure type safety
- ✅ **Test in both themes** - verify dark/light mode compatibility
- ✅ **Include error handling** - handle failures gracefully
- ✅ **Add loading states** - provide user feedback
- ✅ **Document complex logic** - help future developers
- ✅ **Consider performance impact** - optimize where possible
- ✅ **Use UUID PKs in DB tables** - standardize on `UUID` primary keys with `uuid_generate_v4()` defaults

---

## 🎉 Best Practices Summary

1. **Quality First** - Write clean, well-typed, tested code
2. **User Experience** - Consider accessibility, performance, and usability
3. **Consistency** - Follow established patterns and conventions
4. **Collaboration** - Write code that's easy for others to understand
5. **Maintenance** - Consider long-term maintainability and scalability

Remember: Good code is not just functional, but also maintainable, accessible, and delightful to work with! 🚀

---

## 🎨 UI Design Instructions (Synced from `design.md`)

The section below is copied from `/design.md` and is the default UI design guidance for this repository.

# Worklenz UI Design Instructions

Last updated: 2026-04-23

This file defines the UI design rules for this repository. Use it as the source of truth when creating or modifying UI in:
- `worklenz-frontend`
- `worklenz-client-portal`

## 1. Design Principles

- Build for clarity first: dense product UI is acceptable, confusion is not.
- Preserve consistency with existing Worklenz patterns before introducing new visual language.
- Prefer Ant Design components and design tokens over custom primitives.
- Every UI change must work in both `light` and `dark` themes.
- Every user-facing string must be localized; no hardcoded UI text.

## 2. Theming and Tokens

Use theme tokens from Ant Design `ConfigProvider` and `theme.useToken()`.

Baseline repo tokens currently include:
- `colorPrimary: #1890ff`
- `borderRadius: 6`
- `colorBgLayout`: `#f5f5f5` (light), `#141414` (dark)
- `colorBgContainer`: `#ffffff` (light), `#1f1f1f` (dark)
- `colorText`: `rgba(0,0,0,0.88)` (light), `rgba(255,255,255,0.85)` (dark)
- `colorTextSecondary`: `rgba(0,0,0,0.65)` (light), `rgba(255,255,255,0.65)` (dark)

### Rules
- Do not hardcode one-off hex colors inside components when an existing token can express the same intent.
- For conditional theme values, prefer token-driven variants or centralized helper utilities.
- Keep component radii aligned with the system (`6` for controls, `8` for larger containers/cards/tables).

## 3. Typography

- Primary typeface is Inter/system stack configured in theme.
- Maintain readable hierarchy:
  - Page title: `20-28px`
  - Section title: `16-20px`
  - Body text: `13-15px`
  - Meta/helper text: `12-13px`
- Avoid ultra-light weights for core information.
- Keep line-length practical for data-heavy screens.

## 4. Layout and Spacing

- Use existing layout shells and Ant Design layout primitives (`Layout`, `Row`, `Col`, `Flex`, `Space`).
- Follow an 8px rhythm where practical (`4/8/12/16/24/32`).
- Prefer consistent gutter/padding values within a screen.
- Keep table/filter/action bars sticky only when it solves a real navigation problem.

## 5. Component Rules

### Forms
- Use Ant Design `Form` validation patterns.
- Show validation feedback near the field and keep error copy actionable.
- Required fields must be clearly indicated.

### Tables and Lists
- Optimize for scanning:
  - stable column alignment
  - predictable action locations
  - restrained row hover/focus styles
- Row actions should not jump layout when revealed.
- For large data sets, use pagination or virtualization patterns already present in the repo.

### Buttons and Actions
- One clear primary action per section/modal.
- Avoid multiple high-emphasis buttons in the same action group.
- Destructive actions require confirmation.

### Empty, Loading, Error States
- Every async screen must define all three states.
- Empty states should explain next action.
- Error states should provide recovery action (retry/back/contact).

## 6. Responsive Behavior

- Must support desktop, tablet, and mobile breakpoints.
- On narrower screens:
  - collapse non-critical columns/content
  - keep primary actions reachable
  - avoid horizontal scrolling unless data-table context requires it
- Validate modal/drawer behavior for small screens.

## 7. Accessibility

- Ensure keyboard navigation for interactive controls.
- Preserve visible focus states; do not remove focus outline without replacement.
- Use semantic controls and ARIA attributes when semantics are not implicit.
- Maintain adequate text/background contrast in both themes.
- Icon-only buttons require accessible labels/tooltips.

## 8. Motion and Feedback

- Keep motion subtle and functional (`150-300ms` for most transitions).
- Prefer opacity/transform transitions over expensive layout-affecting animation.
- Use progress indicators for operations above ~300ms.
- Do not animate large surfaces unnecessarily in data-dense workflows.

## 9. Localization Rules (Mandatory)

- No hardcoded user-facing text in JSX/TSX.
- Use i18next for all labels, buttons, placeholders, messages, and headings.
- Always include `defaultValue` in translation calls.
- Use interpolation/pluralization features for dynamic content.

## 10. Implementation Do/Don't

### Do
- Reuse existing components/patterns before introducing new ones.
- Use token-based colors and spacing.
- Test in both themes and at multiple viewport sizes.
- Keep UX consistent between `worklenz-frontend` and `worklenz-client-portal` where behavior overlaps.

### Don't
- Introduce theme-breaking hardcoded colors.
- Add new visual patterns for common controls without a product-level reason.
- Ship UI that only looks correct in one theme.
- Merge features with missing loading/error/empty states.

## 11. PR Checklist for UI Changes

- [ ] Works in light theme
- [ ] Works in dark theme
- [ ] Uses i18n (no hardcoded strings)
- [ ] Uses Ant Design patterns and tokens
- [ ] Keyboard and focus behavior verified
- [ ] Responsive behavior verified
- [ ] Loading, empty, and error states covered
- [ ] No obvious layout shift or performance regressions