From d8a3c03554c069eeb67ed3aa0eddc99b8d5b606a Mon Sep 17 00:00:00 2001 From: Flexomatic81 Date: Mon, 23 Feb 2026 20:17:29 +0100 Subject: [PATCH] chore: gitignore agent-memory and remove from tracking Co-Authored-By: Claude Opus 4.6 --- .../agent-memory/backend-specialist/MEMORY.md | 99 ------ .../backend-specialist/testing.md | 65 ---- .../devops-infrastructure-expert/MEMORY.md | 52 --- .../frontend-specialist/MEMORY.md | 325 ------------------ .../frontend-specialist/component-patterns.md | 204 ----------- .../frontend-specialist/shared-package.md | 69 ---- .../integration-specialist/MEMORY.md | 169 --------- .../senior-code-reviewer/MEMORY.md | 123 ------- .../phase7-backend-review.md | 71 ---- .gitignore | 3 + 10 files changed, 3 insertions(+), 1177 deletions(-) delete mode 100644 .claude/agent-memory/backend-specialist/MEMORY.md delete mode 100644 .claude/agent-memory/backend-specialist/testing.md delete mode 100644 .claude/agent-memory/devops-infrastructure-expert/MEMORY.md delete mode 100644 .claude/agent-memory/frontend-specialist/MEMORY.md delete mode 100644 .claude/agent-memory/frontend-specialist/component-patterns.md delete mode 100644 .claude/agent-memory/frontend-specialist/shared-package.md delete mode 100644 .claude/agent-memory/integration-specialist/MEMORY.md delete mode 100644 .claude/agent-memory/senior-code-reviewer/MEMORY.md delete mode 100644 .claude/agent-memory/senior-code-reviewer/phase7-backend-review.md diff --git a/.claude/agent-memory/backend-specialist/MEMORY.md b/.claude/agent-memory/backend-specialist/MEMORY.md deleted file mode 100644 index cc22596..0000000 --- a/.claude/agent-memory/backend-specialist/MEMORY.md +++ /dev/null @@ -1,99 +0,0 @@ -# tOS Backend Architecture Memory - -## Project Structure -- **Location**: `/home/mehmed/Entwicklung/githubProjekte/tOS/apps/api/` -- **Framework**: NestJS 10.3.x with TypeScript strict mode -- **ORM**: Prisma 5.8.x with PostgreSQL -- **Auth**: JWT-based with Keycloak integration support - -## Key Conventions -- **Language**: English for all code/comments -- **Files**: kebab-case, **Variables**: camelCase -- **API Prefix**: `/api/v1/` -- **Global Guards**: JwtAuthGuard -> RolesGuard -> PermissionsGuard -- **IDs**: CUID, **Soft Delete**: `isActive` boolean - -## Security - Encryption (CRITICAL) -- `EncryptionService` in `src/common/services/` (AES-256-GCM) -- **Encrypted fields in Employee model:** - - `salary` - Stored as encrypted String (not Decimal!) - - `bankAccount` - Stored as encrypted JSON string -- Access via `findOne(id, includeSensitive=true)` for decryption -- Config: `ENCRYPTION_KEY` env variable (required in production) - -## Auth Pattern -- Routes protected by default via global JwtAuthGuard -- `@Public()` for open endpoints -- `@Roles('admin', 'hr-manager')` for role-based access -- `@RequirePermissions(Permission.USERS_CREATE)` for fine-grained -- `@CurrentUser()` to get JWT payload - -## Available Roles -admin, hr-manager, team-lead, employee - -## Module Exports -All modules export via `index.ts` barrel files: -- `/modules/index.ts` exports: audit, dashboard, departments, user-preferences, integrations, lean, hr -- `/modules/lean/index.ts` exports: s3-planning, skill-matrix, morning-meeting -- `/modules/hr/index.ts` exports: employees, absences, time-tracking - -## Health Endpoints -- Located at `src/health/` (NOT `src/modules/health/`) -- `GET /health` - Full check (database, memory, modules status) -- `GET /health/liveness` - Kubernetes liveness -- `GET /health/readiness` - Database connectivity -- `ModulesHealthIndicator` reports core/hr/lean/integrations status - -## Test Infrastructure -- **Web (apps/web)**: Vitest 2.x + @testing-library/react + jsdom - - Config: `apps/web/vitest.config.ts` - - Setup: `apps/web/src/test/setup.ts` (imports @testing-library/jest-dom/vitest) - - Scripts: `test` (vitest run), `test:watch` (vitest) -- **API (apps/api)**: Jest 29.x + ts-jest + @nestjs/testing - - Config: inline in `package.json` under `jest` key - - rootDir: `src`, testRegex: `.*\\.spec\\.ts$` - - Module alias: `@/` -> `/` - -## Phase 3: Integrations -Location: `src/modules/integrations/` -Sub-modules: credentials/, sync/, status/, jobs/ -Types: PLENTYONE, ZULIP, TODOIST, FREESCOUT, NEXTCLOUD, ECODMS, GEMBADOCS - -## Phase 4: LEAN -Location: `src/modules/lean/` -- `s3-planning/` - 3S/5S audit planning (permissions: S3_VIEW/CREATE/UPDATE/DELETE/MANAGE) -- `skill-matrix/` - Skills and employee skill entries -- `morning-meeting/` - SQCDM meetings, topics, actions (permissions: MEETING_VIEW/CREATE/UPDATE/DELETE) - -## Phase 5: HR -Location: `src/modules/hr/` -- `employees/` - CRUD, org chart, **encrypted salary + bankAccount** -- `absences/` - Approval workflow (PENDING->APPROVED/REJECTED/CANCELLED) -- `time-tracking/` - Clock in/out, German ArbZG break compliance - -### Absences Workflow -- Auto-approved: SICK, SICK_CHILD -- Vacation balance: 30 days/year, pro-rata by entry date - -### Time Tracking -- German labor law breaks: >6h=30min, >9h=45min -- Monthly summary with overtime calculation - -## Scripts (from root) -```bash -pnpm run dev:api # Development server -pnpm run db:migrate # Run migrations -pnpm run db:generate # Generate Prisma client -pnpm run db:seed # Seed default data -``` - -## Common Patterns -- Use `CommonModule` (@Global) for shared services like EncryptionService -- DTOs with class-validator for input validation -- Swagger decorators for API documentation -- `@AuditLog('Entity', 'ACTION')` for audit trail - -See detailed docs in `agent-memory/backend-specialist/` for: -- [integrations.md](./integrations.md) - Integration details -- [hr-module.md](./hr-module.md) - HR module specifics -- [testing.md](./testing.md) - Test infrastructure details diff --git a/.claude/agent-memory/backend-specialist/testing.md b/.claude/agent-memory/backend-specialist/testing.md deleted file mode 100644 index 098db49..0000000 --- a/.claude/agent-memory/backend-specialist/testing.md +++ /dev/null @@ -1,65 +0,0 @@ -# tOS Test Infrastructure - -## Frontend (apps/web) - Vitest - -### Configuration -- `vitest.config.ts` at project root of apps/web -- Uses `@vitejs/plugin-react` for JSX transform -- jsdom environment for DOM testing -- `globals: true` so `describe/it/expect` are global -- Path alias `@` -> `./src` matching tsconfig -- CSS disabled in tests (`css: false`) -- Setup file: `src/test/setup.ts` imports `@testing-library/jest-dom/vitest` - -### Dependencies (devDependencies) -- vitest ^2.1.8 -- @testing-library/react ^16.1.0 -- @testing-library/jest-dom ^6.6.3 -- @testing-library/user-event ^14.5.2 -- @vitejs/plugin-react ^4.3.4 -- jsdom ^25.0.1 - -### Test Files -- `src/lib/utils.test.ts` - Tests for cn(), getInitials(), capitalize(), truncate(), safeJsonParse(), generateId(), isServer(), isClient() -- `src/components/ui/badge.test.tsx` - Badge component rendering with all variants -- `src/hooks/use-toast.test.ts` - Tests reducer logic and toast() function - -### Run Commands -```bash -pnpm --filter web test # vitest run -pnpm --filter web test:watch # vitest (watch mode) -``` - -## Backend (apps/api) - Jest - -### Configuration -- Inline in `package.json` under `"jest"` key -- ts-jest transform for TypeScript -- Node test environment -- Module alias: `@/` -> `/` (rootDir = src) -- Test regex: `.*\.spec\.ts$` - -### Dependencies (already present) -- jest ^29.7.0 -- ts-jest ^29.1.1 -- @nestjs/testing ^10.3.0 -- @types/jest ^29.5.11 -- supertest ^6.3.3 - -### Test Files -- `src/health/health.controller.spec.ts` - Health controller (check, liveness, readiness) -- `src/common/services/encryption.service.spec.ts` - EncryptionService (encrypt/decrypt, objects, empty strings, generateKey, init) - -### Test Patterns for NestJS -- Use `Test.createTestingModule()` for DI setup -- Mock all dependencies with `{ provide: X, useValue: mockX }` -- Call `module.get(T)` to get the instance under test -- For services with `onModuleInit()`, call it manually in `beforeEach` -- Use `jest.clearAllMocks()` in `afterEach` - -### Run Commands -```bash -pnpm --filter api test # jest -pnpm --filter api test:watch # jest --watch -pnpm --filter api test:cov # jest --coverage -``` diff --git a/.claude/agent-memory/devops-infrastructure-expert/MEMORY.md b/.claude/agent-memory/devops-infrastructure-expert/MEMORY.md deleted file mode 100644 index 873f5d5..0000000 --- a/.claude/agent-memory/devops-infrastructure-expert/MEMORY.md +++ /dev/null @@ -1,52 +0,0 @@ -# tOS Infrastructure Memory - -## Docker Stack -- **Location**: `/home/mehmed/Entwicklung/githubProjekte/tOS/docker/` -- **Compose file**: `docker-compose.yml` (name: tos) -- **Services**: PostgreSQL 16, Redis 7, Keycloak 24.0 -- **Network**: `tos-network` (bridge) -- **Volumes**: `tos-postgres-data`, `tos-redis-data` - -## Ports (Default) -| Service | Port | -|------------|------| -| PostgreSQL | 5432 | -| Redis | 6379 | -| Keycloak | 8080 | -| API | 3001 | -| Frontend | 3000 | - -## Keycloak Configuration -- **Realm**: `tOS` -- **Clients**: `tos-frontend` (public), `tos-backend` (confidential) -- **Roles Hierarchy**: - - admin -> hr-manager, manager, department_head, team-lead, employee - - hr-manager -> employee - - manager -> department_head, employee - - department_head -> team-lead, employee - - team-lead -> employee -- **Test Users**: admin, manager, depthead, employee, hrmanager, teamlead -- **Default passwords**: `123` (temporary) - -## Environment Variables -- **Root `.env.example`**: Application config (NextAuth, Keycloak, API keys) -- **Docker `.env.example`**: Container config (ports, credentials) -- **Critical Production Secrets**: - - `ENCRYPTION_KEY` - 32 bytes for credential encryption - - `JWT_SECRET` - API token signing - - `NEXTAUTH_SECRET` - Session encryption - - `KEYCLOAK_BACKEND_CLIENT_SECRET` - -## Package Scripts -```bash -pnpm docker:up # Start infrastructure -pnpm docker:down # Stop infrastructure -pnpm docker:logs # View logs -pnpm docker:reset # Destroy volumes and restart -pnpm dev # Start dev servers -``` - -## Known Issues / Lessons Learned -- Keycloak 24+ (UBI9) has no curl; use bash TCP redirect for health checks -- Realm import: file must be at `/opt/keycloak/data/import/` with `--import-realm` flag -- Health check `start_period` should be 90s+ for Keycloak (Java startup) diff --git a/.claude/agent-memory/frontend-specialist/MEMORY.md b/.claude/agent-memory/frontend-specialist/MEMORY.md deleted file mode 100644 index fc9e116..0000000 --- a/.claude/agent-memory/frontend-specialist/MEMORY.md +++ /dev/null @@ -1,325 +0,0 @@ -# tOS Frontend - Agent Memory - -## Project Overview -- **Type**: Enterprise Web Dashboard (Next.js 14+ App Router) -- **Location**: `/home/mehmed/Entwicklung/githubProjekte/tOS/apps/web/` -- **Language**: Code/comments in English, UI in German (default) via i18n - -## Tech Stack -- Next.js 14+ with App Router -- TypeScript (strict mode) -- Tailwind CSS + shadcn/ui (new-york style) -- next-themes for dark/light mode -- next-intl for i18n (de default, en supported) -- NextAuth with Keycloak provider -- Framer Motion for animations -- Zustand for client state (sidebar-store, dashboard-store) -- TanStack Query for server state -- TanStack Table for data tables -- Recharts for chart components -- dnd-kit for drag and drop -- date-fns for date formatting -- Lucide React for icons - -## File Structure -``` -apps/web/src/ - app/[locale]/ # Locale-based routing - (auth)/ # Protected routes with sidebar layout - dashboard/ # Widget-based dashboard - settings/ # profile/, preferences/, security/, notifications/ - admin/ # users/, departments/, integrations/ - role protected - lean/ # 3s-planning/, morning-meeting/, skill-matrix/ - hr/ # employees/, time-tracking/, absences/ - integrations/ # Overview + [type]/ dynamic routes - login/ # Public login page - components/ - ui/ # shadcn/ui + DataTable, Badge, Tabs, Switch, etc. - layout/ # Sidebar (collapsible sub-nav), Header - dashboard/ # Widget system (container, grid, registry) - widgets/ # clock, welcome, quick-actions, stats, calendar, activity - integrations/ # orders, chat, tasks, tickets, files, documents - integrations/ # Shared: status-badge, integration-card, connection-test-button - charts/ # bar-chart, line-chart, pie-chart, chart-container - providers/ # SessionProvider, ThemeProvider, QueryProvider - hooks/ # use-toast, use-media-query, use-mounted - integrations/ # use-orders, use-messages, use-tasks, etc. - lib/ # utils, api, auth, motion variants - stores/ # sidebar-store, dashboard-store - types/ # User, UserRole, Department, WidgetConfig, integrations.ts -``` - -## Key Patterns - -### 1. Server/Client Component Split -- `page.tsx` = Server Component (metadata only) -- `*-content.tsx` = Client Component (receives locale prop) - -### 2. Widget System (Phase 2) -- Registry pattern: `widget-registry.ts` defines all widget types -- Drag & drop: dnd-kit with SortableContext -- Persistence: Zustand store with localStorage -- Each widget: WidgetContainer wrapper + specific content - -### 3. Role-Based Navigation -- NavItem has optional `requiredRoles: UserRole[]` -- Sidebar filters items via `filterNavItems(items, userRoles)` -- Roles: admin, manager, department_head, employee - -### 4. DataTable Pattern -- Generic component: `DataTable` -- Use `DataTableColumnHeader` for sortable columns -- Features: search, pagination, column visibility, row selection - -### 5. Chart Components -- Wrap Recharts in `ChartContainer` for consistent styling -- Support loading states, empty states -- Theme-aware colors via CSS variables - -### 6. Integration Hooks (Phase 3) -- TanStack Query with 30s staleTime -- Mock data for development, TODO comments for API replacement -- Query key factories: `ordersKeys`, `messagesKeys`, etc. -- Optimistic updates for complete/toggle actions - -### 7. Integration Widgets -- Widget categories: `integrations` added to registry -- requiredRoles: ['manager', 'admin'] for sensitive widgets -- Each widget uses WidgetContainer + specific hook - -## Sidebar Behavior -- Expanded: 240px, Collapsed: 64px -- Collapsible sub-navigation with ChevronDown animation -- Tooltip shows sub-nav when collapsed - -## i18n Keys -- Flat structure with nested objects: `widgets.clock.name` -- Use ASCII for German (oe, ae, ue) to avoid encoding issues - -## Dependencies Added (Phase 2) -- @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities -- @tanstack/react-table -- @radix-ui/react-checkbox, collapsible, popover, select, tabs -- recharts, date-fns - -## Dependencies Added (Phase 3) -- @radix-ui/react-switch (for Switch component) - -## Integration Types (Phase 3+) -- `plenty-one`: PlentyONE (e-commerce) - OrdersWidget -- `zulip`: ZULIP (chat) - ChatWidget -- `todoist`: Todoist (tasks) - TasksWidget -- `freescout`: FreeScout (helpdesk) - TicketsWidget -- `nextcloud`: Nextcloud (files) - FilesWidget -- `ecodms`: ecoDMS (documents) - DocumentsWidget -- `gembadocs`: GembaDocs (audits/compliance) - GembaDocsWidget - -## LEAN Module Structure - -### File Organization -``` -apps/web/src/ - app/[locale]/(auth)/lean/ - page.tsx # LEAN overview - s3-planning/ - page.tsx # S3 plans overview - [departmentId]/page.tsx # Department detail view - morning-meeting/ - page.tsx # Meetings overview + calendar - morning-meeting-overview-content.tsx - [departmentId]/ - page.tsx # Department SQCDM board - department-meeting-content.tsx - skill-matrix/ - page.tsx # Overview with department cards - skill-matrix-overview-content.tsx - [departmentId]/ - page.tsx # Department matrix grid + gap analysis - department-skill-matrix-content.tsx - components/lean/ - s3/ # S3 Planning components - index.ts # Barrel export - s3-status-cell.tsx # Colored week cell - s3-status-modal.tsx # Status edit dialog - s3-category-card.tsx # Category with week grid - s3-progress-chart.tsx # Pie chart stats - s3-plan-overview.tsx # Plans list with filters - s3-department-view.tsx # Week calendar view - morning-meeting/ # Morning Meeting components - index.ts # Barrel export - meeting-board.tsx # Main board with all 5 SQCDM columns - sqcdm-column.tsx # Single S/Q/C/D/M column - kpi-card.tsx # KPI with traffic light + trend - meeting-timer.tsx # Timer with start/stop, countdown mode - action-list.tsx # Action items container with filters - action-item.tsx # Single action with status/assignee - hooks/lean/ - index.ts # Barrel export - use-s3-plans.ts # Plans CRUD + types - use-s3-status.ts # Status updates - use-meetings.ts # Meeting CRUD + topics/actions - use-meeting-timer.ts # Timer logic (elapsed/countdown) -``` - -### S3 Status Types & Colors -- `NOT_APPLICABLE` (gray): Not started -- `YELLOW`: In progress -- `GREEN`: Completed -- `RED`: Problem/Issue - -### S3 Type Categories -- `SEIRI`: Sort -- `SEITON`: Set in Order -- `SEISO`: Shine - -### API Endpoints (Backend) -- `GET /lean/s3/plans` - List with filters (year, month, departmentId) -- `GET /lean/s3/plans/:id` - Single plan with categories/statuses -- `PUT /lean/s3/status/:id` - Update status entry - -### Skill Matrix Module -``` -components/lean/skill-matrix/ - index.ts # Barrel export - skill-level-badge.tsx # Level badge with color coding (0-4) - skill-cell.tsx # Matrix cell with quick-edit popover - skill-matrix-grid.tsx # Full grid (employees x skills) - skill-gap-chart.tsx # Bar chart for gap analysis - -hooks/lean/ - use-skills.ts # Skills CRUD + categories - use-skill-matrix.ts # Matrix data + gap analysis -``` - -### Skill Level Colors -- `0` (gray): No knowledge -- `1` (red): Basics -- `2` (yellow): Independent -- `3` (green): Expert -- `4` (blue): Can train - -### Skill Matrix API Endpoints (Backend) -- `GET /lean/skills` - List with filters -- `GET /lean/skills/department/:id` - Skills for department -- `GET /lean/skill-matrix/:departmentId` - Full matrix -- `GET /lean/skill-matrix/gaps/:departmentId` - Gap analysis -- `POST /lean/skill-matrix/entries` - Create entry -- `PUT /lean/skill-matrix/entries/:id` - Update entry -- `POST /lean/skill-matrix/entries/bulk` - Bulk upsert - -## HR Module (Phase 5) - -### File Structure -``` -apps/web/src/ - app/[locale]/(auth)/hr/ - page.tsx # HR overview with stats - hr-overview-content.tsx # Client component - employees/ - page.tsx # Employee list - employees-content.tsx - [id]/ - page.tsx # Employee details - employee-detail-content.tsx - new/ - page.tsx # New employee form - new-employee-content.tsx - org-chart/ - page.tsx # Organization chart - org-chart-content.tsx - components/hr/employees/ - index.ts # Barrel export - employee-card.tsx # Quick overview card - employee-list.tsx # DataTable with filters - employee-form.tsx # Create/edit form - org-chart.tsx # Hierarchical tree view - hooks/hr/ - index.ts # Barrel export - use-employees.ts # CRUD + types + mock data -``` - -### Employee Types -- `EmploymentStatus`: active, inactive, on_leave, terminated -- `ContractType`: full_time, part_time, mini_job, intern, trainee, freelance -- Full Employee interface with address, emergency contact - -### Employee Status Colors -- `active` (green) -- `inactive` (gray) -- `on_leave` (yellow) -- `terminated` (red) - -### i18n Keys (hr namespace) -- `hr.title`, `hr.description` -- `hr.employees.*` - List/detail pages -- `hr.stats.*` - Dashboard statistics -- `hr.employeeStatus.*` - Status translations -- `hr.contractType.*` - Contract type translations -- `hr.form.*` - Form sections -- `hr.tabs.*` - Detail view tabs -- `hr.toast.*` - Toast notifications - -### Dependencies Added (Phase 5) -- react-day-picker (for Calendar component) -- react-hook-form + zod (already present) -- @radix-ui/react-progress (for Progress component) - -## HR Time Tracking Module (Phase 5) - -### File Structure -``` -apps/web/src/ - app/[locale]/(auth)/hr/ - time-tracking/ - page.tsx # Time tracking overview - time-tracking-content.tsx # Time clock + entries - [employeeId]/ - page.tsx # Employee time account - employee-time-account-content.tsx - absences/ - page.tsx # Absences overview - absences-content.tsx # Balance + requests - calendar/ - page.tsx # Team calendar view - absence-calendar-content.tsx - requests/ - page.tsx # Manager approval view - absence-requests-content.tsx - components/hr/ - time-tracking/ - index.ts # Barrel export - time-clock.tsx # Web clock (clock in/out, breaks) - time-entry-list.tsx # List of time entries - time-entry-form.tsx # Correction request dialog - time-summary.tsx # Monthly summary with progress - absences/ - index.ts # Barrel export - absence-calendar.tsx # Monthly calendar with absences - absence-request-form.tsx # Create absence request dialog - absence-card.tsx # Single absence with status - absence-approval-list.tsx # Pending requests for managers - vacation-balance.tsx # Vacation quota display - hooks/hr/ - use-time-tracking.ts # Clock in/out, entries, summary - use-absences.ts # Requests, balance, calendar - types/hr.ts # TimeEntry, Absence, VacationBalance types -``` - -### Time Tracking Types -- `TimeEntryStatus`: CLOCKED_IN, ON_BREAK, CLOCKED_OUT -- `TimeEntryType`: REGULAR, OVERTIME, CORRECTED -- `TIME_STATUS_INFO`: Color mapping for status badges - -### Absence Types -- `AbsenceType`: VACATION, SICK, HOME_OFFICE, SPECIAL_LEAVE, UNPAID_LEAVE, TRAINING -- `AbsenceRequestStatus`: PENDING, APPROVED, REJECTED, CANCELLED -- `ABSENCE_TYPE_INFO`: Color + icon mapping -- `ABSENCE_STATUS_INFO`: Status color mapping - -### i18n Keys (hr namespace) -- `hr.timeTracking.*` - Clock, entries, summary -- `hr.absences.*` - Balance, requests, calendar, approvals - -## Related Files -- [shared-package.md](./shared-package.md) - @tos/shared integration guide & differences -- [component-patterns.md](./component-patterns.md) - Code examples diff --git a/.claude/agent-memory/frontend-specialist/component-patterns.md b/.claude/agent-memory/frontend-specialist/component-patterns.md deleted file mode 100644 index 7155397..0000000 --- a/.claude/agent-memory/frontend-specialist/component-patterns.md +++ /dev/null @@ -1,204 +0,0 @@ -# Component Patterns - tOS Frontend - -## Layout Component Pattern -```tsx -// src/components/layout/sidebar.tsx -'use client'; - -import { usePathname } from 'next/navigation'; -import { motion } from 'framer-motion'; -import { useSidebarStore } from '@/stores/sidebar-store'; - -export function Sidebar({ locale }: { locale: string }) { - const { isExpanded, toggleSidebar } = useSidebarStore(); - const pathname = usePathname(); - - return ( - - {/* Content */} - - ); -} -``` - -## Page with Metadata Pattern -```tsx -// page.tsx (Server Component) -import { Metadata } from 'next'; -import { getTranslations } from 'next-intl/server'; -import { ContentComponent } from './content-component'; - -export async function generateMetadata(): Promise { - const t = await getTranslations('namespace'); - return { title: t('title') }; -} - -export default function Page() { - return ; -} - -// content-component.tsx (Client Component) -'use client'; -import { useTranslations } from 'next-intl'; - -export function ContentComponent() { - const t = useTranslations('namespace'); - return
{t('key')}
; -} -``` - -## Zustand Store Pattern -```tsx -// src/stores/sidebar-store.ts -import { create } from 'zustand'; -import { persist } from 'zustand/middleware'; - -interface SidebarState { - isExpanded: boolean; - toggleSidebar: () => void; -} - -export const useSidebarStore = create()( - persist( - (set) => ({ - isExpanded: true, - toggleSidebar: () => set((state) => ({ isExpanded: !state.isExpanded })), - }), - { - name: 'tos-sidebar-state', - partialize: (state) => ({ isExpanded: state.isExpanded }), - } - ) -); -``` - -## Animation Pattern with Framer Motion -```tsx -import { motion } from 'framer-motion'; - -// Staggered list animation - - {items.map((item, index) => ( - - {item.content} - - ))} - -``` - -## shadcn/ui Component with Variants -```tsx -// src/components/ui/button.tsx -import { cva, type VariantProps } from 'class-variance-authority'; - -const buttonVariants = cva( - 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors', - { - variants: { - variant: { - default: 'bg-primary text-primary-foreground hover:bg-primary/90', - destructive: 'bg-destructive text-destructive-foreground', - outline: 'border border-input bg-background hover:bg-accent', - ghost: 'hover:bg-accent hover:text-accent-foreground', - }, - size: { - default: 'h-9 px-4 py-2', - sm: 'h-8 px-3 text-xs', - lg: 'h-10 px-8', - icon: 'h-9 w-9', - }, - }, - defaultVariants: { - variant: 'default', - size: 'default', - }, - } -); - -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean; -} -``` - -## Provider Composition Pattern -```tsx -// src/components/providers/index.tsx -'use client'; - -export function Providers({ children }: { children: ReactNode }) { - return ( - - - - {children} - - - - ); -} -``` - -## i18n Usage Pattern -```tsx -// In components -import { useTranslations } from 'next-intl'; - -export function Component() { - const t = useTranslations('namespace'); - return {t('key', { param: 'value' })}; -} - -// In server components -import { getTranslations } from 'next-intl/server'; - -export async function ServerComponent() { - const t = await getTranslations('namespace'); - return {t('key')}; -} -``` - -## Protected Route Layout Pattern -```tsx -// src/app/[locale]/(auth)/layout.tsx -'use client'; - -export default function AuthLayout({ children, params: { locale } }) { - const { isExpanded } = useSidebarStore(); - - return ( -
-
- -
- - -
-
-
- {children} -
-
-
- ); -} -``` diff --git a/.claude/agent-memory/frontend-specialist/shared-package.md b/.claude/agent-memory/frontend-specialist/shared-package.md deleted file mode 100644 index 2a89e59..0000000 --- a/.claude/agent-memory/frontend-specialist/shared-package.md +++ /dev/null @@ -1,69 +0,0 @@ -# @tos/shared Package Integration - -## Package Location -`packages/shared/` - Built with tsup, outputs CJS + ESM + types to `dist/` - -## Available Exports - -### Utils (`@tos/shared` or `@tos/shared/utils`) -- `formatDate(date, options?)` - German locale, 2-digit format (dd.MM.yyyy) -- `formatTime(date, options?)` - German locale, HH:mm -- `formatDateTime(date)` - Combined date + time -- `calculateWorkingDays(start, end)` - Excludes weekends -- `minutesToHoursAndMinutes(mins)` - Returns { hours, minutes } -- `formatMinutesToTime(mins)` - Returns "HH:MM" string -- `getInitials(firstName, lastName)` - Two-arg version, returns "FL" -- `getFullName(firstName, lastName)` - Returns "First Last" -- `slugify(str)` - URL-safe slug -- `isDefined(value)` - Type guard for non-null/undefined -- `sleep(ms)` - Promise-based delay - -### Constants (`@tos/shared`) -- `DEFAULT_VACATION_DAYS`, `MIN_VACATION_DAYS` -- `STANDARD_WORKING_HOURS_PER_WEEK/DAY`, `MAX_WORKING_HOURS_PER_DAY` -- `DEFAULT_BREAK_MINUTES`, `REQUIRED_BREAK_MINUTES`, `EXTENDED_BREAK_MINUTES` -- `SKILL_LEVELS`, `S3_CATEGORIES`, `SQCDM_CATEGORIES` -- `HTTP_STATUS`, `DATE_FORMATS` -- `API_VERSION`, `API_PREFIX`, `DEFAULT_PAGE_SIZE`, `MAX_PAGE_SIZE` -- `PERMISSIONS`, `ROLE_PERMISSIONS` - -### Types (`@tos/shared` or `@tos/shared/types`) -- `User`, `UserRole`, `UserPreferences`, `DashboardWidgetConfig`, `NotificationPreferences` -- `CreateUserDto`, `UpdateUserDto` -- `Department`, `DepartmentCode`, `DepartmentWithStats`, `CreateDepartmentDto`, `UpdateDepartmentDto` -- `Employee`, `ContractType`, `TimeEntry`, `TimeEntryType`, `Absence`, `AbsenceType`, `ApprovalStatus` -- `AuthUser`, `TokenPayload`, `LoginRequest`, `AuthResponse`, `Permission` -- Skill Matrix: `Skill`, `SkillMatrixEntry`, `SkillMatrix`, `SkillGapAnalysis`, etc. - -## Integration Patterns - -### Web App (apps/web) -- `transpilePackages: ['@tos/shared']` in next.config.mjs (transpiles source directly) -- `"@tos/shared": "workspace:*"` in package.json -- Import directly: `import { getInitials } from '@tos/shared'` - -### API App (apps/api) -- `"@tos/shared": "workspace:*"` in package.json -- Uses built dist (CJS) - requires `pnpm --filter @tos/shared build` first -- Import: `import { calculateWorkingDays, DEFAULT_VACATION_DAYS } from '@tos/shared'` - -## Key Differences: Local vs Shared - -### getInitials -- **Shared**: `getInitials(firstName: string, lastName: string)` - two args -- **Web local** (`@/lib/utils`): `getInitials(name: string)` - single full name string, splits on space -- Both coexist; use shared in components with firstName/lastName, local in header with full name - -### Date Formatting -- **Shared**: `formatDate()` uses `{ day: '2-digit', month: '2-digit', year: 'numeric' }`, hardcoded `de-DE` -- **Web local**: `formatDate()` uses `{ year: 'numeric', month: 'long', day: 'numeric' }`, accepts locale param -- **Web local**: `formatDateShort()` is equivalent to shared `formatDate()` but accepts locale param -- NOT interchangeable - different output format - -### sleep -- Identical in both - web local now re-exports from `@tos/shared` - -### ApprovalStatus / ContractType -- **Shared**: UPPERCASE (`'PENDING'`, `'FULL_TIME'`) -- **Web types**: lowercase (`'pending'`, `'full_time'`) -- NOT interchangeable - different casing convention diff --git a/.claude/agent-memory/integration-specialist/MEMORY.md b/.claude/agent-memory/integration-specialist/MEMORY.md deleted file mode 100644 index 4dd9c51..0000000 --- a/.claude/agent-memory/integration-specialist/MEMORY.md +++ /dev/null @@ -1,169 +0,0 @@ -# Integration Specialist Memory - tOS Project - -## Project Structure -- **API Location**: `/apps/api/src/` -- **Integrations Module**: `/apps/api/src/modules/integrations/` -- **Connectors**: `/apps/api/src/modules/integrations/connectors/` - -## Phase 3 Connector Implementation (Completed) - -### Base Infrastructure -- `base-connector.ts`: Abstract base class with axios, retry logic, rate limiting -- `errors/integration.errors.ts`: Custom error classes (Auth, Connection, RateLimit, API, Config, Validation) - -### Implemented Connectors - -#### PlentyONE (`/connectors/plentyone/`) -- **Auth**: OAuth2 Client Credentials flow -- **Token Management**: Auto-refresh with 5-minute buffer -- **Endpoints**: Orders, Stock, Statistics/Revenue -- **Rate Limiting**: 60s timeout (PlentyONE can be slow) -- **API Base**: `{baseUrl}/rest` - -#### ZULIP (`/connectors/zulip/`) -- **Auth**: Basic Auth (email + API key) -- **Endpoints**: Messages, Streams, Users -- **API Base**: `{baseUrl}/api/v1` -- **Note**: Form-encoded POST requests for some endpoints - -#### Todoist (`/connectors/todoist/`) -- **Auth**: Bearer Token -- **Endpoints**: Tasks, Projects, Sections, Labels -- **API Base**: `https://api.todoist.com/rest/v2` -- **Note**: Uses X-Request-Id header for idempotency - -#### FreeScout (`/connectors/freescout/`) -- **Auth**: API Key via `X-FreeScout-API-Key` header -- **Endpoints**: Conversations, Mailboxes, Customers, Tags -- **API Base**: `{baseUrl}/api` -- **API Docs**: https://github.com/freescout-helpdesk/freescout/wiki/API - -#### Nextcloud (`/connectors/nextcloud/`) -- **Auth**: Basic Auth (username + app-password) -- **Endpoints**: WebDAV Files, OCS Share API, CalDAV Calendar (basic) -- **API Bases**: `{baseUrl}/remote.php/dav/files/{user}` (WebDAV), `{baseUrl}/ocs/v2.php` (OCS) -- **Note**: WebDAV uses PROPFIND/MKCOL/MOVE/COPY; OCS needs `OCS-APIRequest: true` header - -#### ecoDMS (`/connectors/ecodms/`) -- **Auth**: Session-based (login returns session ID, use `X-Session-Id` header) -- **Endpoints**: Documents, Folders, Classifications, Search -- **API Base**: `{baseUrl}/api/v1` -- **Note**: Session auto-refresh before expiry; supports file upload with FormData - -## Environment Variables - -```bash -# PlentyONE -PLENTYONE_BASE_URL= -PLENTYONE_CLIENT_ID= -PLENTYONE_CLIENT_SECRET= - -# ZULIP -ZULIP_BASE_URL= -ZULIP_EMAIL= -ZULIP_API_KEY= - -# Todoist -TODOIST_API_TOKEN= - -# FreeScout -FREESCOUT_API_URL= -FREESCOUT_API_KEY= - -# Nextcloud -NEXTCLOUD_URL= -NEXTCLOUD_USERNAME= -NEXTCLOUD_PASSWORD= - -# ecoDMS -ECODMS_API_URL= -ECODMS_USERNAME= -ECODMS_PASSWORD= -ECODMS_API_VERSION=v1 -``` - -## Key Patterns - -### Retry Logic -- Exponential backoff with jitter (0.5-1.5x multiplier) -- Default: 3 retries, 1s initial delay, 30s max delay -- Retry on: 429, 500, 502, 503, 504 - -### Error Handling -- `IntegrationConnectionError`: Network issues (retryable) -- `IntegrationAuthError`: 401 responses (not retryable) -- `IntegrationRateLimitError`: 429 responses (retryable after delay) -- `IntegrationApiError`: Other API errors (retryable if 5xx) - -### Module Structure -Each connector follows pattern: -1. `{name}.types.ts` - TypeScript interfaces -2. `{name}.connector.ts` - Low-level API client -3. `{name}.service.ts` - Business logic layer -4. `{name}.controller.ts` - HTTP endpoints -5. `{name}.module.ts` - NestJS module -6. `dto/*.dto.ts` - Request/Response DTOs - -## API Endpoints - -``` -GET /integrations - Overview all integrations -GET /integrations/:type/status - Integration status -GET /integrations/:type/health - Health check - -POST /integrations/plentyone/test -GET /integrations/plentyone/orders -GET /integrations/plentyone/orders/:id -GET /integrations/plentyone/stock -GET /integrations/plentyone/stats - -POST /integrations/zulip/test -GET /integrations/zulip/messages -POST /integrations/zulip/messages -GET /integrations/zulip/streams -GET /integrations/zulip/users - -POST /integrations/todoist/test -GET /integrations/todoist/tasks -POST /integrations/todoist/tasks -PUT /integrations/todoist/tasks/:id -DELETE /integrations/todoist/tasks/:id -GET /integrations/todoist/projects - -# FreeScout -POST /integrations/freescout/test -GET /integrations/freescout/conversations -GET /integrations/freescout/conversations/:id -POST /integrations/freescout/conversations -POST /integrations/freescout/conversations/:id/reply -GET /integrations/freescout/mailboxes -GET /integrations/freescout/customers -GET /integrations/freescout/tags - -# Nextcloud -POST /integrations/nextcloud/test -GET /integrations/nextcloud/files -GET /integrations/nextcloud/files/*path -POST /integrations/nextcloud/files/upload -DELETE /integrations/nextcloud/files/*path -GET /integrations/nextcloud/calendar/events - -# ecoDMS -POST /integrations/ecodms/test -GET /integrations/ecodms/documents -GET /integrations/ecodms/documents/:id -POST /integrations/ecodms/documents/search -GET /integrations/ecodms/documents/:id/download -GET /integrations/ecodms/folders -GET /integrations/ecodms/classifications -``` - -## Dependencies -- `axios`: ^1.6.0 (HTTP client) -- axios types included in axios package - -## Notes -- All connectors check `isConfigured()` before operations -- `getMissingConfig()` returns list of missing env vars -- Logging in development mode by default -- All API responses transformed to DTOs diff --git a/.claude/agent-memory/senior-code-reviewer/MEMORY.md b/.claude/agent-memory/senior-code-reviewer/MEMORY.md deleted file mode 100644 index 35d62ae..0000000 --- a/.claude/agent-memory/senior-code-reviewer/MEMORY.md +++ /dev/null @@ -1,123 +0,0 @@ -# tOS Project Code Review Memory - -## Project Overview -- **Type:** Enterprise Web Operating System with HR, LEAN modules -- **Stack:** Next.js 14 + NestJS 10 + Prisma + PostgreSQL + Keycloak -- **Structure:** pnpm monorepo with turbo (apps/web, apps/api, packages/shared) - -## Code Standards (from PLAN.md) -| Area | Language | Convention | -|------|----------|------------| -| Code & Comments | English | Required | -| UI Text | German (via i18n) | next-intl | -| Variables | camelCase | `employeeId` | -| Components | PascalCase | `DashboardWidget` | -| Files | kebab-case | `user-service.ts` | -| Constants | UPPER_SNAKE_CASE | `MAX_VACATION_DAYS` | - -## Critical Patterns Found - -### Authentication -- Global `JwtAuthGuard` with `@Public()` opt-out decorator -- Global `RolesGuard` with `@Roles()` decorator -- Keycloak integration via NextAuth (frontend) and passport-jwt (backend) -- **IMPORTANT:** Always verify JWT signatures, never just decode -- Guards registered in correct order: JWT -> Roles -> Permissions (app.module.ts L74-88) -- JWT strategy validates user exists and is active on every request - -### Frontend Architecture -- **Server/Client split:** Server page.tsx -> Client *-content.tsx -- **State:** Zustand (sidebar, dashboard), TanStack Query (server state) -- **i18n:** next-intl with de.json/en.json, default locale = "de" -- **Dashboard:** dnd-kit widget grid, widget registry pattern -- **Styling:** Tailwind + shadcn/ui, HSL CSS vars, dark mode via class - -### Integration Architecture (Phase 3 - Disabled) -- **Location:** `apps/api/integrations.backup/` -- Only PlentyONE/Zulip/Todoist extend BaseConnector -- FreeScout/Nextcloud/ecoDMS/GembaDocs have independent implementations - -### Keycloak Client ID Mismatch (CRITICAL - RECURRING) -- Realm: `tos-frontend` / `tos-backend` -- apps/api/.env: `tos-api` | apps/web/.env: `tos-nextauth` (MISMATCH) - -## Key Issues to Watch -1. **params API:** Mixed sync/async patterns across pages -2. **Hardcoded German:** dashboard-content.tsx, widget-grid.tsx bypass i18n -3. **Mock Data:** HR hooks (employees, time-tracking, absences) use mock data -4. **Type Conflicts:** types/index.ts vs types/hr.ts have conflicting exports -5. **Auth Layout:** `(auth)/layout.tsx` is `'use client'` -- blocks SSR -6. **Error pages:** Link to `/dashboard` without locale prefix -7. **ENCRYPTION_KEY:** `optional()` in validation -- must be required - -### Backend-Specific Issues (from Phase 7 Review) -8. **Morning Meeting Permissions:** ALL endpoints use DASHBOARD_VIEW -- any user can CRUD meetings -9. **Private method access:** time-tracking.controller.ts L237-239 uses bracket notation `this.service['privateMethod']` -10. **Prisma cleanDatabase():** Uses Promise.all ignoring FK constraints (prisma.service.ts L48-61) -11. **Roles guard leaks info:** Error messages reveal required role names (roles.guard.ts L31-33) -12. **enableImplicitConversion:** In ValidationPipe (main.ts L44) -- can cause type coercion bugs -13. **Break tracking via string parsing:** time-tracking uses note field for break detection (L216-219, L257-258) -14. **Audit interceptor:** oldData always undefined (audit.interceptor.ts L60), salary not sanitized (L131) -15. **Unregistered interceptors:** LoggingInterceptor and TimeoutInterceptor defined but never registered -16. **N+1 queries:** skill-entries.service.ts analyzeGaps (L515-523), s3-planning findAll (L173-178) -17. **bulkUpsert not transactional:** skill-entries.service.ts L429-476 -- partial failures possible -18. **No backdating limit:** Manual time entries have no restriction on how far back entries can be created -19. **Holiday calculation missing:** absences calculateWorkingDays does not account for public holidays -20. **Vacation carry-over TODO:** BUrlG compliance gap (absences.service.ts L979) - -## File Locations -| Purpose | Path | -|---------|------| -| Prisma Schema | `apps/api/prisma/schema.prisma` | -| Frontend Types | `apps/web/src/types/` | -| HR Hooks | `apps/web/src/hooks/hr/` | -| LEAN Hooks | `apps/web/src/hooks/lean/` | -| Dashboard | `apps/web/src/components/dashboard/` | -| i18n Messages | `apps/web/messages/` | -| Integration Backup | `apps/api/integrations.backup/` | -| Auth Guards | `apps/api/src/auth/guards/` | -| Auth Permissions | `apps/api/src/auth/permissions/` | -| Encryption Service | `apps/api/src/common/services/encryption.service.ts` | -| HR Employees | `apps/api/src/modules/hr/employees/` | -| HR Time Tracking | `apps/api/src/modules/hr/time-tracking/` | -| HR Absences | `apps/api/src/modules/hr/absences/` | -| LEAN Skill Matrix | `apps/api/src/modules/lean/skill-matrix/` | -| LEAN Morning Meeting | `apps/api/src/modules/lean/morning-meeting/` | -| LEAN S3 Planning | `apps/api/src/modules/lean/s3-planning/` | -| Audit Module | `apps/api/src/modules/audit/` | -| Config Validation | `apps/api/src/config/config.validation.ts` | - -## Review History - -### Phase 7 Full Backend Review (2026-02-06) -- **Overall: 7.8/10** | 3 Critical, 14 Important issues -- Scores: Auth 8 | Prisma 7 | HR/Emp 8 | HR/Time 7 | HR/Abs 8 -- LEAN/Skill 8 | LEAN/Morning 7 | LEAN/S3 8 | Dashboard 8 -- Common 8 | Users 8 | Audit 7 | app.module 9 -- See: `phase7-backend-review.md` - -### Phase 6 Frontend Review (2026-02-06) -- 5 Critical, 9 Important, detailed 10-area review -- See: `phase6-frontend-review.md` - -### Infrastructure + Integration Review (2026-02-06) -- Docker 7/10 | Keycloak 7/10 | Env 4/10 | Integration 6/10 -- See: `infra-integration-review.md` - -### Phase 5 Review (2026-02-05) -- HR modules: Employees, Time Tracking, Absences - -### Phase 3 Review (2026-02-05) -- Integration connectors reviewed; module now disabled - -### Phase 1 Review (2024) -- JWT validation, type sync, CORS, Keycloak fixes applied - -## Backend Architecture Notes -- Global guards chain: JwtAuthGuard -> RolesGuard -> PermissionsGuard -- Response envelope via TransformInterceptor: `{success, data, timestamp}` -- Global HttpExceptionFilter catches all exceptions, no internal leaks -- AES-256-GCM encryption for salary + bank accounts (fixed salt issue noted) -- Audit via decorator `@AuditLog()` + global AuditInterceptor -- Permissions enum uses entity:action format (e.g., `employees:read`) -- DEFAULT_ROLE_PERMISSIONS maps roles to permission arrays diff --git a/.claude/agent-memory/senior-code-reviewer/phase7-backend-review.md b/.claude/agent-memory/senior-code-reviewer/phase7-backend-review.md deleted file mode 100644 index 4ed6c97..0000000 --- a/.claude/agent-memory/senior-code-reviewer/phase7-backend-review.md +++ /dev/null @@ -1,71 +0,0 @@ -# Phase 7 - Full Backend Code Review (2026-02-06) - -## Overall Score: 7.8/10 - -## Module Scores - -| Module | Score | Key Issue | -|--------|-------|-----------| -| Auth (guards, strategy, decorators) | 8/10 | Role names leaked in error messages | -| Prisma (service, module) | 7/10 | cleanDatabase() ignores FK constraints | -| HR/Employees | 8/10 | `as any` type casts for encrypted data | -| HR/Time Tracking | 7/10 | Break tracking via string parsing, private method access | -| HR/Absences | 8/10 | Missing holiday calc, vacation carry-over TODO | -| LEAN/Skill Matrix | 8/10 | N+1 in analyzeGaps, non-transactional bulkUpsert | -| LEAN/Morning Meeting | 7/10 | ALL endpoints use DASHBOARD_VIEW permission | -| LEAN/S3 Planning | 8/10 | File upload MIME not validated, N+1 in findAll | -| Dashboard | 8/10 | Hardcoded role strings | -| Common (filters, interceptors) | 8/10 | Logging/Timeout interceptors never registered | -| Users | 8/10 | GET /users has no permission restriction | -| Audit | 7/10 | oldData always undefined, salary not sanitized | -| app.module + main.ts | 9/10 | enableImplicitConversion risk | - -## Critical Issues (3) - -### 1. Morning Meeting Permission Escalation -- **File:** `apps/api/src/modules/lean/morning-meeting/morning-meeting.controller.ts` -- **Lines:** 47, 59, 66, 79, 99, 120, 149, 159, 170, 183, 193, 211, 221, 234, 249, 259, 270 -- **Issue:** ALL endpoints (including create, update, delete) use `Permission.DASHBOARD_VIEW` -- **Impact:** Any authenticated user with dashboard access can create/modify/delete morning meetings - -### 2. Private Method Access via Bracket Notation -- **File:** `apps/api/src/modules/hr/time-tracking/time-tracking.controller.ts` -- **Lines:** 237-239 -- **Issue:** `this.timeTrackingService['getEmployeeByUserId'](user.sub)` accesses private method -- **Impact:** Circumvents TypeScript access modifiers, fragile to refactoring - -### 3. Prisma cleanDatabase() with Promise.all -- **File:** `apps/api/src/prisma/prisma.service.ts` -- **Lines:** 48-61 -- **Issue:** Deletes all tables in parallel ignoring foreign key constraints -- **Impact:** Can fail in production/staging if FK constraints exist; should use sequential deletion or raw SQL truncate cascade - -## Important Issues (14) - -1. **Roles guard leaks role names** - roles.guard.ts L31-33 -2. **Permissions guard leaks permission names** - permissions.guard.ts -3. **enableImplicitConversion in ValidationPipe** - main.ts L44 -4. **Break tracking via note string parsing** - time-tracking.service.ts L216-219, L257-258 -5. **No backdating limit** for manual time entries -6. **Holiday calculation missing** in absences calculateWorkingDays -7. **Vacation carry-over not implemented** - absences.service.ts L979 (BUrlG) -8. **Event queue in-memory only** - absences.service.ts L1414 -9. **N+1 query in analyzeGaps** - skill-entries.service.ts L515-523 -10. **bulkUpsert not transactional** - skill-entries.service.ts L429-476 -11. **File upload MIME not validated** - s3-planning.controller.ts -12. **LoggingInterceptor + TimeoutInterceptor never registered** -13. **GET /users no permission check** - users.controller.ts L88-97 -14. **Audit oldData always undefined** - audit.interceptor.ts L60 - -## Positive Observations - -- JWT verification (not just decode) with user existence check on every request -- AES-256-GCM encryption for sensitive employee data (salary, bank account) -- Consistent error response format via global HttpExceptionFilter -- Response envelope pattern via TransformInterceptor -- ArbZG break rules correctly implemented in time tracking -- Comprehensive absence workflow with approval chain -- Global ValidationPipe with whitelist + forbidNonWhitelisted -- Proper soft delete patterns for employees -- Well-structured module hierarchy (HrModule -> sub-modules) -- Swagger/OpenAPI documentation on all endpoints diff --git a/.gitignore b/.gitignore index edabebe..67c2fbd 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,9 @@ build/ .env.*.local !.env.example +# Claude Code +.claude/agent-memory/ + # IDE .idea/ .vscode/