{"owner":"bluewave-labs","repo":"Checkmate","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nCheckmate is an open-source uptime and infrastructure monitoring application. It monitors server hardware, uptime, response times, and incidents with real-time alerts. The companion agent [Capture](https://github.com/bluewave-labs/capture) provides infrastructure metrics (CPU, RAM, disk, temperature).\n\n## Development Commands\n\n### Client (React/Vite)\n```bash\ncd client\nnpm install\nnpm run dev -- --port 10001 --strictPort   # Local dev port is 10001 (5173 is used by another project on this machine)\nnpm run build            # TypeScript check + production build\nnpm run lint             # ESLint (strict, max-warnings 0)\nnpm run format           # Prettier formatting\nnpm run format-check     # Check formatting\n```\n\nServer `.env` on this machine is configured with `CLIENT_HOST=\"http://localhost:10001\"` to match the client dev port. If you change the client port, keep `.env` in sync.\n\n### Server (Node.js/Express)\n```bash\ncd server\nnpm install\nnpm run dev              # Start with hot-reload (nodemon + tsx) at http://localhost:52345\nnpm run build            # TypeScript compile + path alias resolution\nnpm run test             # Run Jest tests with coverage\nnpm run lint             # ESLint v9\nnpm run lint-fix         # Auto-fix lint issues\nnpm run format           # Prettier formatting\n```\n\n### Docker Development\n```bash\ndocker build -f docker/Dockerfile -t checkmate .          # build the mono image (server + built client)\ndocker compose -f docker/dev/docker-compose.yaml up       # local full stack (builds image, runs mongo + worker)\ndocker run -d -p 27017:27017 -v uptime_mongo_data:/data/db --name uptime_database_mongo mongo:8.0   # just a dev database\n```\n\n## Environment Setup\n\n### Server `.env` (minimum required)\n```env\nCLIENT_HOST=\"http://localhost:5173\"\nJWT_SECRET=\"my_secret_key_change_this\"\nDB_CONNECTION_STRING=\"mongodb://localhost:27017/uptime_db\"\nTOKEN_TTL=\"99d\"\nORIGIN=\"localhost\"\nLOG_LEVEL=\"debug\"\n```\n\n### Client `.env`\n```env\nVITE_APP_API_BASE_URL=\"http://localhost:52345/api/v1\"\nVITE_APP_LOG_LEVEL=\"debug\"\n```\n\n## Architecture\n\n### Monorepo Structure\n- `/client` - React 18 + TypeScript + Vite + MUI frontend\n- `/server` - Node.js 20+ + Express + TypeScript backend\n- `/docker` - Multi-environment Docker configs (dev, staging, prod, arm, mono)\n\n### Backend Layers\n```\nserver/src/\n├── api/             # HTTP layer\n│   ├── controllers/   # Route handlers (authController, monitorController, etc.)\n│   ├── middleware/    # verifyJWT, rateLimiter, sanitization, responseHandler\n│   ├── routes/        # API route definitions\n│   └── validation/    # Zod request-payload schemas\n├── domain/          # Business logic + data access, one folder per entity\n│   ├── monitors/      # e.g. monitor.service.ts, monitor.repository.ts, monitor.type.ts\n│   ├── checks/\n│   ├── incidents/\n│   └── …              # users, teams, status-pages, notifications, etc.\n├── service/         # Cross-cutting services (e.g. infrastructure/)\n├── config/          # App config wiring (controllers, routes, services, envValidation)\n├── db/\n│   └── migration/   # Database migrations (run on startup)\n├── templates/       # Email/notification templates\n├── types/           # Shared const tuples + derived types\n└── utils/           # Shared utilities\n```\n\n### Frontend Structure\n```\nclient/src/\n├── Components/      # Reusable UI components\n├── Pages/           # Page components (Auth, Uptime, Infrastructure, Incidents, etc.)\n├── Features/        # Redux slices (Auth, UI)\n├── Hooks/           # Custom React hooks\n├── Utils/           # Utilities (NetworkService.js is main API client)\n├── Validation/      # Input validation\n└── locales/         # i18n translations\n```\n\n### API\n- Base URL: `/api/v1`\n- Documentation: `http://localhost:52345/api-docs` (Swagger UI)\n- OpenAPI spec: `/server/openapi.json`\n\n### Key Technologies\n- **State Management**: Redux Toolkit + Redux-Persist\n- **Data Fetching**: SWR + Axios\n- **Database**: MongoDB with Mongoose ODM\n- **Queue/Cache**: Redis + BullMQ + Pulse (cron scheduling)\n- **i18n**: i18next + react-i18next (translations via PoEditor)\n\n---\n\n## Backend Architecture Patterns\n\n### Repository Pattern & Separation of Concerns\n\nThe backend enforces a strict three-layer separation between HTTP handling, business logic, and data access:\n\n```\nRequest → Controller → Service → Repository → MongoDB (Mongoose)\n```\n\n- **Controllers** (`/controllers`) handle HTTP concerns only: parsing request params, calling the appropriate service, and returning a response via the `responseHandler` middleware. They contain no business logic.\n- **Services** (`/service/business`) contain all business logic: deciding whether an incident should be created, whether a notification should fire, what state a monitor is in, etc.\n- **Repositories** (`/repositories`) are the sole layer that talks to MongoDB through Mongoose. They expose clean, reusable query methods (e.g. `findByMonitorId`, `createCheck`) so that services never construct raw DB queries directly.\n\nThis separation makes each layer independently testable and keeps Mongoose-specific code out of business logic. When adding a new feature, the pattern to follow is: add a repository method for any new DB query, call it from a service, and expose it via a controller route.\n\n### Monitoring Flow: From Check to Notification\n\nBackground monitoring runs on a scheduled queue, not on the HTTP request cycle. The high-level flow for uptime monitoring is:\n\n```\nPulse (cron) → BullMQ Job → StatusService\n                                 ├── performs HTTP/port/ping check\n                                 ├── saves Check via CheckRepository\n                                 ├── evaluates monitor state change\n                                 │     └── calls IncidentService (create / resolve incident)\n                                 └── calls NotificationService (email, Slack, Discord, webhook)\n```\n\n1. **Pulse** (cron scheduler) enqueues a job into a **BullMQ** queue for each active monitor at its configured interval.\n2. A **BullMQ worker** picks up the job and calls `StatusService`, which performs the actual check (HTTP request, TCP port probe, ping, etc.).\n3. The result is persisted as a `Check` document via the repository layer.\n4. `StatusService` compares the new result against the monitor's previous state. If the monitor transitions from up → down (or down → up), it delegates to `IncidentService` to open or resolve an `Incident` document.\n5. On a state change, `NotificationService` reads the monitor's configured `Notification` documents and dispatches alerts to all enabled channels (email, Discord, Slack, webhooks).\n\n### Queue System (BullMQ + Redis)\n\nRedis serves two roles: job queue storage for BullMQ and ephemeral caching. BullMQ manages concurrency, retries, and backpressure for monitoring jobs, ensuring checks are processed reliably even under load.\n\n- Each monitor type (HTTP, port, ping, infrastructure) maps to its own queue worker so failures in one type don't block others.\n- Job scheduling interval is driven by the `interval` field on the `Monitor` model.\n- Failed jobs are retried with configurable backoff before being moved to a dead-letter state.\n- Redis is also used to cache frequently read data (e.g. aggregated stats) to reduce MongoDB query pressure.\n\nWhen working on anything related to check scheduling, incident lifecycle, or notifications, trace the flow starting from the relevant BullMQ worker rather than from the controller layer.\n\n---\n\n## Code Conventions\n\n### Coding conventions (mandatory)\nRead `docs/coding-conventions.md` before touching any `.tsx` or `.ts` file. The doc covers both frontend and backend rules, all enforced in code review.\n\n**Universal — rule 0:** look at peer files first and follow the established pattern. Don't sneak in novel shapes.\n\n**Frontend (`client/src`):**\n1. Prefer MUI native props over `sx` (e.g. `color={…}`, `bgcolor={…}`, `mt={…}` — not `sx={{ color, bgcolor, mt }}`).\n2. Use the full theme path for colors: `color={theme.palette.text.secondary}`, never `color=\"text.secondary\"` (greppability).\n3. No hardcoded literals — use `LAYOUT.*`, `typographyLevels.*`, `theme.shape.borderRadius`, `theme.palette.*`.\n4. Use `useTheme()` inside components; don't `import { theme } from \"@/Utils/Theme/Theme\"`.\n5. Pair runtime tuples with derived types: `const X = [...] as const; type X = (typeof X)[number]`.\n\n**Backend (`server/src`):**\n6. Layering: Controller → Service → Repository → Mongoose. No DB calls outside repositories.\n7. Provider conventions: DI for stdlib clients, `SERVICE_NAME` + `TIMEOUT_MS` constants, `timeRequest()` helper, inline `setTimeout` race for timeout, outer try/catch into `AppError`.\n8. Mongoose schema fields with closed value sets must declare `enum` reusing the same `types/*` const tuple.\n9. Provider tests at `server/test/unit/providers/network/<name>.test.ts`, `from \"@jest/globals\"`, `testStatusProviderContract`, inline `setup()` per test (not `beforeEach`).\n10. Centralize validation enums in `types/*` const tuples; never inline `z.enum([…])` more than once.\n11. New entity fields must land in the validator's `*ResponseSchema` so the auto-generated OpenAPI spec sees them.\n\n### Internationalization\nAll user-facing strings must use the translation function:\n```javascript\nt('your.key')  // Never hardcode UI strings\n```\n\n### Branching\n- Always branch from `develop` (not master)\n- Use descriptive names: `feat/add-alerts`, `fix/login-error`\n- PRs target `develop` branch\n\n### Formatting\n- **Client**: Prettier with `printWidth: 90`, tabs, double quotes\n- **Server**: Prettier with `printWidth: 150`, tabs, double quotes\n- Both use ESLint with strict settings\n\n### Testing\nServer tests use Jest (with `--experimental-vm-modules` for ESM):\n```bash\nnpm test                              # Run all tests with coverage\nnpm test -- -t \"pattern\"              # Run tests matching name pattern\nnpm test -- path/to/file.test.ts      # Run a specific file\n```\nTest files: `server/test/**/*.test.ts`\n\n## Database Models\n\nKey Mongoose models in `/server/src/db/models/`:\n- **Monitor** - Monitoring configuration (website, infrastructure, port, etc.)\n- **Check** - Individual monitoring check results\n- **Incident** - Downtime incidents\n- **User** - User accounts\n- **Team** - Team/workspace management\n- **StatusPage** - Public status pages\n- **Notification** - Alert configuration (email, Discord, Slack, webhooks)\n- **MaintenanceWindow** - Scheduled maintenance periods\n- **AppSettings** - Global application settings"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nCheckmate is an open-source uptime and infrastructure monitoring application. It monitors server hardware, uptime, response times, and incidents with real-time alerts. The companion agent [Capture](https://github.com/bluewave-labs/capture) provides infrastructure metrics (CPU, RAM, disk, temperature).\n\n## Development Commands\n\n### Client (React/Vite)\n```bash\ncd client\nnpm install\nnpm run dev -- --port 10001 --strictPort   # Local dev port is 10001 (5173 is used by another project on this machine)\nnpm run build            # TypeScript check + production build\nnpm run lint             # ESLint (strict, max-warnings 0)\nnpm run format           # Prettier formatting\nnpm run format-check     # Check formatting\n```\n\nServer `.env` on this machine is configured with `CLIENT_HOST=\"http://localhost:10001\"` to match the client dev port. If you change the client port, keep `.env` in sync.\n\n### Server (Node.js/Express)\n```bash\ncd server\nnpm install\nnpm run dev              # Start with hot-reload (nodemon + tsx) at http://localhost:52345\nnpm run build            # TypeScript compile + path alias resolution\nnpm run test             # Run Jest tests with coverage\nnpm run lint             # ESLint v9\nnpm run lint-fix         # Auto-fix lint issues\nnpm run format           # Prettier formatting\n```\n\n### Docker Development\n```bash\ndocker build -f docker/Dockerfile -t checkmate .          # build the mono image (server + built client)\ndocker compose -f docker/dev/docker-compose.yaml up       # local full stack (builds image, runs mongo + worker)\ndocker run -d -p 27017:27017 -v uptime_mongo_data:/data/db --name uptime_database_mongo mongo:8.0   # just a dev database\n```\n\n## Environment Setup\n\n### Server `.env` (minimum required)\n```env\nCLIENT_HOST=\"http://localhost:5173\"\nJWT_SECRET=\"my_secret_key_change_this\"\nDB_CONNECTION_STRING=\"mongodb://localhost:27017/uptime_db\"\nTOKEN_TTL=\"99d\"\nORIGIN=\"localhost\"\nLOG_LEVEL=\"debug\"\n```\n\n### Client `.env`\n```env\nVITE_APP_API_BASE_URL=\"http://localhost:52345/api/v1\"\nVITE_APP_LOG_LEVEL=\"debug\"\n```\n\n## Architecture\n\n### Monorepo Structure\n- `/client` - React 18 + TypeScript + Vite + MUI frontend\n- `/server` - Node.js 20+ + Express + TypeScript backend\n- `/docker` - Multi-environment Docker configs (dev, staging, prod, arm, mono)\n\n### Backend Layers\n```\nserver/src/\n├── api/             # HTTP layer\n│   ├── controllers/   # Route handlers (authController, monitorController, etc.)\n│   ├── middleware/    # verifyJWT, rateLimiter, sanitization, responseHandler\n│   ├── routes/        # API route definitions\n│   └── validation/    # Zod request-payload schemas\n├── domain/          # Business logic + data access, one folder per entity\n│   ├── monitors/      # e.g. monitor.service.ts, monitor.repository.ts, monitor.type.ts\n│   ├── checks/\n│   ├── incidents/\n│   └── …              # users, teams, status-pages, notifications, etc.\n├── service/         # Cross-cutting services (e.g. infrastructure/)\n├── config/          # App config wiring (controllers, routes, services, envValidation)\n├── db/\n│   └── migration/   # Database migrations (run on startup)\n├── templates/       # Email/notification templates\n├── types/           # Shared const tuples + derived types\n└── utils/           # Shared utilities\n```\n\n### Frontend Structure\n```\nclient/src/\n├── Components/      # Reusable UI components\n├── Pages/           # Page components (Auth, Uptime, Infrastructure, Incidents, etc.)\n├── Features/        # Redux slices (Auth, UI)\n├── Hooks/           # Custom React hooks\n├── Utils/           # Utilities (NetworkService.js is main API client)\n├── Validation/      # Input validation\n└── locales/         # i18n translations\n```\n\n### API\n- Base URL: `/api/v1`\n- Documentation: `http://localhost:52345/api-docs` (Swagger UI)\n- OpenAPI spec: `/server/openapi.json`\n\n### Key Technologies\n- **State Management**: Redux Toolkit + Redux-Persist\n- **Data Fetching**: SWR + Axios\n- **Database**: MongoDB with Mongoose ODM\n- **Queue/Cache**: Redis + BullMQ + Pulse (cron scheduling)\n- **i18n**: i18next + react-i18next (translations via PoEditor)\n\n---\n\n## Backend Architecture Patterns\n\n### Repository Pattern & Separation of Concerns\n\nThe backend enforces a strict three-layer separation between HTTP handling, business logic, and data access:\n\n```\nRequest → Controller → Service → Repository → MongoDB (Mongoose)\n```\n\n- **Controllers** (`/controllers`) handle HTTP concerns only: parsing request params, calling the appropriate service, and returning a response via the `responseHandler` middleware. They contain no business logic.\n- **Services** (`/service/business`) contain all business logic: deciding whether an incident should be created, whether a notification should fire, what state a monitor is in, etc.\n- **Repositories** (`/repositories`) are the sole layer that talks to MongoDB through Mongoose. They expose clean, reusable query methods (e.g. `findByMonitorId`, `createCheck`) so that services never construct raw DB queries directly.\n\nThis separation makes each layer independently testable and keeps Mongoose-specific code out of business logic. When adding a new feature, the pattern to follow is: add a repository method for any new DB query, call it from a service, and expose it via a controller route.\n\n### Monitoring Flow: From Check to Notification\n\nBackground monitoring runs on a scheduled queue, not on the HTTP request cycle. The high-level flow for uptime monitoring is:\n\n```\nPulse (cron) → BullMQ Job → StatusService\n                                 ├── performs HTTP/port/ping check\n                                 ├── saves Check via CheckRepository\n                                 ├── evaluates monitor state change\n                                 │     └── calls IncidentService (create / resolve incident)\n                                 └── calls NotificationService (email, Slack, Discord, webhook)\n```\n\n1. **Pulse** (cron scheduler) enqueues a job into a **BullMQ** queue for each active monitor at its configured interval.\n2. A **BullMQ worker** picks up the job and calls `StatusService`, which performs the actual check (HTTP request, TCP port probe, ping, etc.).\n3. The result is persisted as a `Check` document via the repository layer.\n4. `StatusService` compares the new result against the monitor's previous state. If the monitor transitions from up → down (or down → up), it delegates to `IncidentService` to open or resolve an `Incident` document.\n5. On a state change, `NotificationService` reads the monitor's configured `Notification` documents and dispatches alerts to all enabled channels (email, Discord, Slack, webhooks).\n\n### Queue System (BullMQ + Redis)\n\nRedis serves two roles: job queue storage for BullMQ and ephemeral caching. BullMQ manages concurrency, retries, and backpressure for monitoring jobs, ensuring checks are processed reliably even under load.\n\n- Each monitor type (HTTP, port, ping, infrastructure) maps to its own queue worker so failures in one type don't block others.\n- Job scheduling interval is driven by the `interval` field on the `Monitor` model.\n- Failed jobs are retried with configurable backoff before being moved to a dead-letter state.\n- Redis is also used to cache frequently read data (e.g. aggregated stats) to reduce MongoDB query pressure.\n\nWhen working on anything related to check scheduling, incident lifecycle, or notifications, trace the flow starting from the relevant BullMQ worker rather than from the controller layer.\n\n---\n\n## Code Conventions\n\n### Coding conventions (mandatory)\nRead `docs/coding-conventions.md` before touching any `.tsx` or `.ts` file. The doc covers both frontend and backend rules, all enforced in code review.\n\n**Universal — rule 0:** look at peer files first and follow the established pattern. Don't sneak in novel shapes.\n\n**Frontend (`client/src`):**\n1. Prefer MUI native props over `sx` (e.g. `color={…}`, `bgcolor={…}`, `mt={…}` — not `sx={{ color, bgcolor, mt }}`).\n2. Use the full theme path for colors: `color={theme.palette.text.secondary}`, never `color=\"text.secondary\"` (greppability).\n3. No hardcoded literals — use `LAYOUT.*`, `typographyLevels.*`, `theme.shape.borderRadius`, `theme.palette.*`.\n4. Use `useTheme()` inside components; don't `import { theme } from \"@/Utils/Theme/Theme\"`.\n5. Pair runtime tuples with derived types: `const X = [...] as const; type X = (typeof X)[number]`.\n\n**Backend (`server/src`):**\n6. Layering: Controller → Service → Repository → Mongoose. No DB calls outside repositories.\n7. Provider conventions: DI for stdlib clients, `SERVICE_NAME` + `TIMEOUT_MS` constants, `timeRequest()` helper, inline `setTimeout` race for timeout, outer try/catch into `AppError`.\n8. Mongoose schema fields with closed value sets must declare `enum` reusing the same `types/*` const tuple.\n9. Provider tests at `server/test/unit/providers/network/<name>.test.ts`, `from \"@jest/globals\"`, `testStatusProviderContract`, inline `setup()` per test (not `beforeEach`).\n10. Centralize validation enums in `types/*` const tuples; never inline `z.enum([…])` more than once.\n11. New entity fields must land in the validator's `*ResponseSchema` so the auto-generated OpenAPI spec sees them.\n\n### Internationalization\nAll user-facing strings must use the translation function:\n```javascript\nt('your.key')  // Never hardcode UI strings\n```\n\n### Branching\n- Always branch from `develop` (not master)\n- Use descriptive names: `feat/add-alerts`, `fix/login-error`\n- PRs target `develop` branch\n\n### Formatting\n- **Client**: Prettier with `printWidth: 90`, tabs, double quotes\n- **Server**: Prettier with `printWidth: 150`, tabs, double quotes\n- Both use ESLint with strict settings\n\n### Testing\nServer tests use Jest (with `--experimental-vm-modules` for ESM):\n```bash\nnpm test                              # Run all tests with coverage\nnpm test -- -t \"pattern\"              # Run tests matching name pattern\nnpm test -- path/to/file.test.ts      # Run a specific file\n```\nTest files: `server/test/**/*.test.ts`\n\n## Database Models\n\nKey Mongoose models in `/server/src/db/models/`:\n- **Monitor** - Monitoring configuration (website, infrastructure, port, etc.)\n- **Check** - Individual monitoring check results\n- **Incident** - Downtime incidents\n- **User** - User accounts\n- **Team** - Team/workspace management\n- **StatusPage** - Public status pages\n- **Notification** - Alert configuration (email, Discord, Slack, webhooks)\n- **MaintenanceWindow** - Scheduled maintenance periods\n- **AppSettings** - Global application settings"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nCheckmate is an open-source uptime and infrastructure monitoring application. It monitors server hardware, uptime, response times, and incidents with real-time alerts. The companion agent [Capture](https://github.com/bluewave-labs/capture) provides infrastructure metrics (CPU, RAM, disk, temperature).\n\n## Development Commands\n\n### Client (React/Vite)\n```bash\ncd client\nnpm install\nnpm run dev -- --port 10001 --strictPort   # Local dev port is 10001 (5173 is used by another project on this machine)\nnpm run build            # TypeScript check + production build\nnpm run lint             # ESLint (strict, max-warnings 0)\nnpm run format           # Prettier formatting\nnpm run format-check     # Check formatting\n```\n\nServer `.env` on this machine is configured with `CLIENT_HOST=\"http://localhost:10001\"` to match the client dev port. If you change the client port, keep `.env` in sync.\n\n### Server (Node.js/Express)\n```bash\ncd server\nnpm install\nnpm run dev              # Start with hot-reload (nodemon + tsx) at http://localhost:52345\nnpm run build            # TypeScript compile + path alias resolution\nnpm run test             # Run Jest tests with coverage\nnpm run lint             # ESLint v9\nnpm run lint-fix         # Auto-fix lint issues\nnpm run format           # Prettier formatting\n```\n\n### Docker Development\n```bash\ndocker build -f docker/Dockerfile -t checkmate .          # build the mono image (server + built client)\ndocker compose -f docker/dev/docker-compose.yaml up       # local full stack (builds image, runs mongo + worker)\ndocker run -d -p 27017:27017 -v uptime_mongo_data:/data/db --name uptime_database_mongo mongo:8.0   # just a dev database\n```\n\n## Environment Setup\n\n### Server `.env` (minimum required)\n```env\nCLIENT_HOST=\"http://localhost:5173\"\nJWT_SECRET=\"my_secret_key_change_this\"\nDB_CONNECTION_STRING=\"mongodb://localhost:27017/uptime_db\"\nTOKEN_TTL=\"99d\"\nORIGIN=\"localhost\"\nLOG_LEVEL=\"debug\"\n```\n\n### Client `.env`\n```env\nVITE_APP_API_BASE_URL=\"http://localhost:52345/api/v1\"\nVITE_APP_LOG_LEVEL=\"debug\"\n```\n\n## Architecture\n\n### Monorepo Structure\n- `/client` - React 18 + TypeScript + Vite + MUI frontend\n- `/server` - Node.js 20+ + Express + TypeScript backend\n- `/docker` - Multi-environment Docker configs (dev, staging, prod, arm, mono)\n\n### Backend Layers\n```\nserver/src/\n├── api/             # HTTP layer\n│   ├── controllers/   # Route handlers (authController, monitorController, etc.)\n│   ├── middleware/    # verifyJWT, rateLimiter, sanitization, responseHandler\n│   ├── routes/        # API route definitions\n│   └── validation/    # Zod request-payload schemas\n├── domain/          # Business logic + data access, one folder per entity\n│   ├── monitors/      # e.g. monitor.service.ts, monitor.repository.ts, monitor.type.ts\n│   ├── checks/\n│   ├── incidents/\n│   └── …              # users, teams, status-pages, notifications, etc.\n├── service/         # Cross-cutting services (e.g. infrastructure/)\n├── config/          # App config wiring (controllers, routes, services, envValidation)\n├── db/\n│   └── migration/   # Database migrations (run on startup)\n├── templates/       # Email/notification templates\n├── types/           # Shared const tuples + derived types\n└── utils/           # Shared utilities\n```\n\n### Frontend Structure\n```\nclient/src/\n├── Components/      # Reusable UI components\n├── Pages/           # Page components (Auth, Uptime, Infrastructure, Incidents, etc.)\n├── Features/        # Redux slices (Auth, UI)\n├── Hooks/           # Custom React hooks\n├── Utils/           # Utilities (NetworkService.js is main API client)\n├── Validation/      # Input validation\n└── locales/         # i18n translations\n```\n\n### API\n- Base URL: `/api/v1`\n- Documentation: `http://localhost:52345/api-docs` (Swagger UI)\n- OpenAPI spec: `/server/openapi.json`\n\n### Key Technologies\n- **State Management**: Redux Toolkit + Redux-Persist\n- **Data Fetching**: SWR + Axios\n- **Database**: MongoDB with Mongoose ODM\n- **Queue/Cache**: Redis + BullMQ + Pulse (cron scheduling)\n- **i18n**: i18next + react-i18next (translations via PoEditor)\n\n---\n\n## Backend Architecture Patterns\n\n### Repository Pattern & Separation of Concerns\n\nThe backend enforces a strict three-layer separation between HTTP handling, business logic, and data access:\n\n```\nRequest → Controller → Service → Repository → MongoDB (Mongoose)\n```\n\n- **Controllers** (`/controllers`) handle HTTP concerns only: parsing request params, calling the appropriate service, and returning a response via the `responseHandler` middleware. They contain no business logic.\n- **Services** (`/service/business`) contain all business logic: deciding whether an incident should be created, whether a notification should fire, what state a monitor is in, etc.\n- **Repositories** (`/repositories`) are the sole layer that talks to MongoDB through Mongoose. They expose clean, reusable query methods (e.g. `findByMonitorId`, `createCheck`) so that services never construct raw DB queries directly.\n\nThis separation makes each layer independently testable and keeps Mongoose-specific code out of business logic. When adding a new feature, the pattern to follow is: add a repository method for any new DB query, call it from a service, and expose it via a controller route.\n\n### Monitoring Flow: From Check to Notification\n\nBackground monitoring runs on a scheduled queue, not on the HTTP request cycle. The high-level flow for uptime monitoring is:\n\n```\nPulse (cron) → BullMQ Job → StatusService\n                                 ├── performs HTTP/port/ping check\n                                 ├── saves Check via CheckRepository\n                                 ├── evaluates monitor state change\n                                 │     └── calls IncidentService (create / resolve incident)\n                                 └── calls NotificationService (email, Slack, Discord, webhook)\n```\n\n1. **Pulse** (cron scheduler) enqueues a job into a **BullMQ** queue for each active monitor at its configured interval.\n2. A **BullMQ worker** picks up the job and calls `StatusService`, which performs the actual check (HTTP request, TCP port probe, ping, etc.).\n3. The result is persisted as a `Check` document via the repository layer.\n4. `StatusService` compares the new result against the monitor's previous state. If the monitor transitions from up → down (or down → up), it delegates to `IncidentService` to open or resolve an `Incident` document.\n5. On a state change, `NotificationService` reads the monitor's configured `Notification` documents and dispatches alerts to all enabled channels (email, Discord, Slack, webhooks).\n\n### Queue System (BullMQ + Redis)\n\nRedis serves two roles: job queue storage for BullMQ and ephemeral caching. BullMQ manages concurrency, retries, and backpressure for monitoring jobs, ensuring checks are processed reliably even under load.\n\n- Each monitor type (HTTP, port, ping, infrastructure) maps to its own queue worker so failures in one type don't block others.\n- Job scheduling interval is driven by the `interval` field on the `Monitor` model.\n- Failed jobs are retried with configurable backoff before being moved to a dead-letter state.\n- Redis is also used to cache frequently read data (e.g. aggregated stats) to reduce MongoDB query pressure.\n\nWhen working on anything related to check scheduling, incident lifecycle, or notifications, trace the flow starting from the relevant BullMQ worker rather than from the controller layer.\n\n---\n\n## Code Conventions\n\n### Coding conventions (mandatory)\nRead `docs/coding-conventions.md` before touching any `.tsx` or `.ts` file. The doc covers both frontend and backend rules, all enforced in code review.\n\n**Universal — rule 0:** look at peer files first and follow the established pattern. Don't sneak in novel shapes.\n\n**Frontend (`client/src`):**\n1. Prefer MUI native props over `sx` (e.g. `color={…}`, `bgcolor={…}`, `mt={…}` — not `sx={{ color, bgcolor, mt }}`).\n2. Use the full theme path for colors: `color={theme.palette.text.secondary}`, never `color=\"text.secondary\"` (greppability).\n3. No hardcoded literals — use `LAYOUT.*`, `typographyLevels.*`, `theme.shape.borderRadius`, `theme.palette.*`.\n4. Use `useTheme()` inside components; don't `import { theme } from \"@/Utils/Theme/Theme\"`.\n5. Pair runtime tuples with derived types: `const X = [...] as const; type X = (typeof X)[number]`.\n\n**Backend (`server/src`):**\n6. Layering: Controller → Service → Repository → Mongoose. No DB calls outside repositories.\n7. Provider conventions: DI for stdlib clients, `SERVICE_NAME` + `TIMEOUT_MS` constants, `timeRequest()` helper, inline `setTimeout` race for timeout, outer try/catch into `AppError`.\n8. Mongoose schema fields with closed value sets must declare `enum` reusing the same `types/*` const tuple.\n9. Provider tests at `server/test/unit/providers/network/<name>.test.ts`, `from \"@jest/globals\"`, `testStatusProviderContract`, inline `setup()` per test (not `beforeEach`).\n10. Centralize validation enums in `types/*` const tuples; never inline `z.enum([…])` more than once.\n11. New entity fields must land in the validator's `*ResponseSchema` so the auto-generated OpenAPI spec sees them.\n\n### Internationalization\nAll user-facing strings must use the translation function:\n```javascript\nt('your.key')  // Never hardcode UI strings\n```\n\n### Branching\n- Always branch from `develop` (not master)\n- Use descriptive names: `feat/add-alerts`, `fix/login-error`\n- PRs target `develop` branch\n\n### Formatting\n- **Client**: Prettier with `printWidth: 90`, tabs, double quotes\n- **Server**: Prettier with `printWidth: 150`, tabs, double quotes\n- Both use ESLint with strict settings\n\n### Testing\nServer tests use Jest (with `--experimental-vm-modules` for ESM):\n```bash\nnpm test                              # Run all tests with coverage\nnpm test -- -t \"pattern\"              # Run tests matching name pattern\nnpm test -- path/to/file.test.ts      # Run a specific file\n```\nTest files: `server/test/**/*.test.ts`\n\n## Database Models\n\nKey Mongoose models in `/server/src/db/models/`:\n- **Monitor** - Monitoring configuration (website, infrastructure, port, etc.)\n- **Check** - Individual monitoring check results\n- **Incident** - Downtime incidents\n- **User** - User accounts\n- **Team** - Team/workspace management\n- **StatusPage** - Public status pages\n- **Notification** - Alert configuration (email, Discord, Slack, webhooks)\n- **MaintenanceWindow** - Scheduled maintenance periods\n- **AppSettings** - Global application settings","category":"root","tokens":2666}]}