{"id":23701024,"url":"https://github.com/lennetech/nest-server","last_synced_at":"2026-04-11T20:22:25.714Z","repository":{"id":37850406,"uuid":"192883751","full_name":"lenneTech/nest-server","owner":"lenneTech","description":"Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).","archived":false,"fork":false,"pushed_at":"2026-02-03T20:04:31.000Z","size":8333,"stargazers_count":11,"open_issues_count":5,"forks_count":2,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2026-02-04T03:41:43.285Z","etag":null,"topics":["graphql","helper","library","mikroorm","mongodb","nestjs","server","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lenneTech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-06-20T08:46:03.000Z","updated_at":"2026-02-03T12:25:08.000Z","dependencies_parsed_at":"2023-12-13T13:28:54.741Z","dependency_job_id":"9fc0c2cc-e239-45fa-aac8-4977be8beb78","html_url":"https://github.com/lenneTech/nest-server","commit_stats":{"total_commits":223,"total_committers":7,"mean_commits":"31.857142857142858","dds":"0.32735426008968604","last_synced_commit":"3b5c61b9076b1c40689e6a2592b7f40f1236916a"},"previous_names":[],"tags_count":231,"template":false,"template_full_name":null,"purl":"pkg:github/lenneTech/nest-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lenneTech%2Fnest-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lenneTech%2Fnest-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lenneTech%2Fnest-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lenneTech%2Fnest-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lenneTech","download_url":"https://codeload.github.com/lenneTech/nest-server/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lenneTech%2Fnest-server/sbom","scorecard":{"id":584248,"data":{"date":"2025-08-11","repo":{"name":"github.com/lenneTech/nest-server","commit":"4c4ee0135aba9a8b37928faa4df8b05328b1c959"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.6,"checks":[{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":4,"reason":"Found 9/21 approved changesets -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"20 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/lenneTech/nest-server/build.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/lenneTech/nest-server/build.yml/develop?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/lenneTech/nest-server/build.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/lenneTech/nest-server/build.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/lenneTech/nest-server/publish.yml/develop?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/lenneTech/nest-server/publish.yml/develop?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/lenneTech/nest-server/publish.yml/develop?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/lenneTech/nest-server/publish.yml/develop?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/build.yml:33","Warn: npmCommand not pinned by hash: .github/workflows/publish.yml:32","Info:   0 out of   5 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-44fp-w29j-9vj5","Warn: Project is vulnerable to: GHSA-4pg4-qvpc-4q3h","Warn: Project is vulnerable to: GHSA-g5hg-p3ph-g8qg","Warn: Project is vulnerable to: GHSA-fjgf-rc76-4x9p","Warn: Project is vulnerable to: GHSA-x5gf-qvw8-r2rm","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T20:00:21.521Z","repository_id":37850406,"created_at":"2025-08-20T20:00:21.521Z","updated_at":"2025-08-20T20:00:21.521Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29293156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T03:42:42.660Z","status":"ssl_error","status_checked_at":"2026-02-10T03:42:41.897Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","helper","library","mikroorm","mongodb","nestjs","server","typescript"],"created_at":"2024-12-30T09:31:33.021Z","updated_at":"2026-04-11T20:22:25.705Z","avatar_url":"https://github.com/lenneTech.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lenne.Tech Nest Server\n\nAn enterprise-grade extension layer on top of [NestJS](https://nestjs.com/) for building secure, scalable server applications with **GraphQL**, **REST/Swagger**, and **MongoDB**.\n\n[![License](https://img.shields.io/github/license/lenneTech/nest-server)](/LICENSE)\n[![npm version](https://img.shields.io/npm/v/@lenne.tech/nest-server)](https://www.npmjs.com/package/@lenne.tech/nest-server)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D%2020-brightgreen)](https://nodejs.org/)\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- [Features Overview](#features-overview)\n- [Architecture](#architecture)\n- [API-First Design](#api-first-design)\n- [Authentication](#authentication)\n- [Roles \u0026 Permissions](#roles--permissions)\n- [Multi-Tenancy](#multi-tenancy)\n- [Scalability](#scalability)\n- [API Versioning](#api-versioning)\n- [Webhook Support](#webhook-support)\n- [External System Integration](#external-system-integration)\n- [Core Modules](#core-modules)\n- [Configuration](#configuration)\n- [Development](#development)\n- [Documentation](#documentation)\n- [License](#license)\n\n## Quick Start\n\nThe fastest way to get started is via the [lenne.Tech CLI](https://github.com/lenneTech/cli) with the [starter project](https://github.com/lenneTech/nest-server-starter):\n\n```bash\nnpm install -g @lenne.tech/cli\nlt server create \u003cServerName\u003e\ncd \u003cServerName\u003e\npnpm start\n```\n\nOr install directly as a package:\n\n```bash\npnpm add @lenne.tech/nest-server\n```\n\n### Create a new module\n\n```bash\nlt server module \u003cModuleName\u003e\n```\n\nThis generates a complete module with model, inputs, resolver, controller, and service.\n\n## Features Overview\n\n| Category | Features |\n|----------|----------|\n| **API-First** | GraphQL (Apollo Server) + REST with Swagger/OpenAPI, dual API surface from single codebase |\n| **Authentication** | BetterAuth (IAM) with JWT, sessions, 2FA/TOTP, Passkey/WebAuthn, social login; Legacy JWT auth |\n| **Authorization** | Extensible role-based access control, field-level restrictions, system roles, hierarchy roles |\n| **Database** | MongoDB via Mongoose, CrudService with security pipeline, advanced filtering \u0026 pagination |\n| **Multi-Tenancy** | Header-based tenant isolation, membership management, hierarchy roles, auto-filtering |\n| **File Handling** | GridFS file storage, resumable uploads via TUS protocol (up to 50 GB) |\n| **Security** | Defense-in-depth: input validation, password hashing, role guard, audit fields, response filtering |\n| **Integration** | SCIM support, OAuth providers, multi-provider email (Mailjet/Brevo/SMTP), webhook support via lifecycle hooks |\n| **Scalability** | Stateless design, distributed migration locking, request-scoped isolation, query complexity analysis |\n| **API Versioning** | NestJS-native URI/header/media-type versioning, GraphQL schema evolution with deprecations |\n| **DevOps** | Health checks, database migrations, cron jobs, permissions reporting, system setup |\n\n## Architecture\n\n### Modular Extensibility\n\nThe framework is built on a **Module Inheritance Pattern** — all core modules are designed to be extended through class inheritance in consuming projects:\n\n```typescript\n// Your project extends core classes — full control via override + super()\nexport class UserService extends CoreUserService {\n  override async create(input, serviceOptions) {\n    // Custom pre-processing (validation, enrichment, ...)\n    const result = await super.create(input, serviceOptions);\n    // Custom post-processing (notifications, logging, ...)\n    return result;\n  }\n}\n```\n\n**Why inheritance over hooks/events:**\n- **Full control**: Override methods and precisely define what happens before/after `super()` calls\n- **Selective override**: Skip parts of the parent implementation entirely for custom logic\n- **Type safety**: TypeScript inheritance ensures proper typing and IDE support\n- **No silent failures**: No runtime event systems or hooks that can fail silently\n\n### Two-Layer Structure\n\n- `src/core/` — Reusable framework components (exported via npm, extended by projects)\n- `src/server/` — Internal test/demo implementation (not exported)\n\nEvery core module supports both **auto-registration** (zero-config) and **manual registration** (full customization via extended module). New modules can be added alongside existing ones without modifying the framework.\n\n### Framework Stack\n\n- [NestJS](https://nestjs.com/) — Server framework\n- [Apollo Server](https://www.apollographql.com/docs/apollo-server/) — GraphQL API (optional, disable via `graphQl: false`)\n- [Mongoose](https://mongoosejs.com/) — MongoDB ODM\n- [Swagger/OpenAPI](https://swagger.io/) — REST API documentation\n\n## API-First Design\n\nThe server follows an API-first approach where API contracts are the primary interface:\n\n### Dual API Surface\n\nBoth **GraphQL** and **REST** endpoints are served from the same codebase and business logic. The `@UnifiedField()` decorator generates schemas for both APIs simultaneously:\n\n```typescript\n@UnifiedField({ description: 'User email address', isOptional: false })\nemail: string;\n// → Generates: GraphQL @Field() + Swagger @ApiProperty() + class-validator checks\n```\n\n### Documented API Structure\n\n- **GraphQL Introspection** — Full schema introspection for client code generation (configurable via `graphQl.introspection`)\n- **Swagger/OpenAPI** — Auto-generated REST API documentation from decorators\n- **SpectaQL** — Visual GraphQL documentation (`pnpm run docs`)\n- **Permissions Dashboard** — Interactive HTML report of all endpoints, roles, and security checks (`/permissions`)\n\n### GraphQL Features\n\n- Custom scalars: `Date`, `DateTime`, `JSON`, `Any`\n- WebSocket subscriptions with authentication\n- Query complexity analysis (DoS prevention)\n- File upload support via `graphql-upload`\n- Automatic enum registration\n\n## API Versioning\n\nNestJS provides built-in [API versioning](https://docs.nestjs.com/techniques/versioning) support with multiple strategies. Projects can enable versioning for REST endpoints:\n\n| Strategy | Example | Use Case |\n|----------|---------|----------|\n| **URI** | `/v1/users`, `/v2/users` | Most common, explicit in URL |\n| **Header** | `X-API-Version: 2` | Clean URLs, version in header |\n| **Media Type** | `Accept: application/vnd.app.v2+json` | Content negotiation |\n\n```typescript\n// main.ts — enable URI versioning\napp.enableVersioning({ type: VersioningType.URI });\n\n// controller — assign to version\n@Controller({ path: 'users', version: '2' })\nexport class UsersV2Controller { ... }\n\n// or per-route\n@Get()\n@Version('2')\nasync findAll() { ... }\n```\n\n**GraphQL** APIs are evolved through schema additions and field deprecations (`@deprecated`) rather than versioning, following the [GraphQL best practice](https://graphql.org/learn/best-practices/#versioning) of continuous evolution.\n\n## Webhook Support\n\nThe framework provides webhook capabilities through two mechanisms:\n\n### BetterAuth Lifecycle Hooks\n\nBetterAuth supports [hooks](https://www.better-auth.com/docs/concepts/hooks) that intercept authentication lifecycle events. Projects can extend the BetterAuth service via the Module Inheritance Pattern to react to these events:\n\n```typescript\nexport class AuthService extends CoreBetterAuthService {\n  override async signIn(input, serviceOptions) {\n    const result = await super.signIn(input, serviceOptions);\n    // Trigger webhook after successful sign-in\n    await this.webhookService.dispatch('auth.sign-in', { userId: result.user.id });\n    return result;\n  }\n}\n```\n\nAuthentication events that can be intercepted include: sign-in, sign-up, sign-out, session creation, token refresh, email verification, 2FA verification, and more.\n\n### Module Inheritance for Custom Webhooks\n\nAny service method can be extended to dispatch webhooks via the Module Inheritance Pattern:\n\n```typescript\nexport class ProjectService extends CoreProjectService {\n  override async create(input, serviceOptions) {\n    const project = await super.create(input, serviceOptions);\n    // Dispatch webhook on project creation\n    await this.webhookService.dispatch('project.created', project);\n    return project;\n  }\n}\n```\n\nThis approach allows projects to add webhook dispatching to any CRUD operation or custom business logic without modifying the framework.\n\n## Authentication\n\nTwo authentication systems are available — BetterAuth (recommended) and Legacy JWT auth:\n\n### BetterAuth (IAM) — Recommended\n\nModern, session-based authentication with plugin architecture:\n\n| Feature | Config |\n|---------|--------|\n| **JWT tokens** | `betterAuth.jwt: true` |\n| **Two-Factor (2FA/TOTP)** | `betterAuth.twoFactor: true` |\n| **Passkey/WebAuthn** | `betterAuth.passkey: true` |\n| **Social login** (Google, GitHub, Apple, ...) | `betterAuth.socialProviders: { ... }` |\n| **Email verification** | `betterAuth.emailVerification: { ... }` |\n| **Rate limiting** | `betterAuth.rateLimit: { max: 10 }` |\n| **Cross-subdomain cookies** | `betterAuth.crossSubDomainCookies: true` |\n| **Disable sign-up** | `betterAuth.emailAndPassword.disableSignUp: true` |\n\nThree integration patterns: zero-config, config-based, or manual (`autoRegister: false`).\n\nBetterAuth provides **lifecycle hooks** for reacting to authentication events (sign-in, sign-up, session creation, etc.), enabling integration with external systems. See [Webhook Support](#webhook-support) for details.\n\n### Legacy Auth (JWT)\n\nPassport-based JWT authentication with sign-in, sign-up, refresh tokens, and rate limiting. Runs in parallel with BetterAuth during migration. Legacy endpoints can be disabled via `auth.legacyEndpoints.enabled: false`.\n\nA built-in **migration status query** (`betterAuthMigrationStatus`) tracks progress and indicates when legacy auth can be safely disabled.\n\n## Roles \u0026 Permissions\n\nThe role and permission system is designed for extensibility — from simple role checks to complex multi-tenant hierarchies.\n\n### System Roles (Runtime Checks)\n\nSystem roles (`S_` prefix) are evaluated dynamically at runtime, never stored in the database:\n\n| Role | Purpose |\n|------|---------|\n| `S_USER` | Any authenticated user |\n| `S_VERIFIED` | Email-verified users |\n| `S_CREATOR` | Creator of the resource |\n| `S_SELF` | User accessing own data |\n| `S_EVERYONE` | Public access |\n| `S_NO_ONE` | Permanently locked |\n\n### Method \u0026 Field-Level Authorization\n\n```typescript\n// Method-level: who can call this endpoint?\n@Roles(RoleEnum.ADMIN)\nasync deleteUser() { ... }\n\n// Field-level: who can see/modify this field?\n@Restricted(RoleEnum.S_SELF, RoleEnum.ADMIN)\nemail: string;\n\n// Membership-based: only team members can see this field\n@Restricted({ memberOf: 'teamMembers' })\ninternalNotes: string;\n```\n\n### Custom Role Hierarchies\n\nProjects can define custom role hierarchies beyond the built-in roles:\n\n```typescript\n// Custom hierarchy with level-based comparison\nconst HR = createHierarchyRoles({ viewer: 1, editor: 2, admin: 3, owner: 4 });\n\n@Roles(HR.EDITOR) // requires level \u003e= 2 (editor, admin, or owner)\nasync editDocument() { ... }\n```\n\n### Resource-Level Security\n\nEvery model can override `securityCheck()` for fine-grained, context-aware access control:\n\n```typescript\nexport class Project extends CorePersistenceModel {\n  override securityCheck(user: any, force?: boolean): this {\n    // Remove sensitive fields based on user context\n    if (!this.hasRole(user, RoleEnum.ADMIN)) {\n      this.budget = undefined;\n    }\n    return this;\n  }\n}\n```\n\n### Permissions Reporting\n\nThe built-in Permissions module scans all endpoints and generates security audit reports (HTML dashboard, JSON, Markdown) showing coverage of `@Roles`, `@Restricted`, and `securityCheck()` across the entire API.\n\n## Multi-Tenancy\n\nFull multi-tenancy support with header-based tenant isolation, membership management, and automatic data filtering:\n\n```typescript\n// config.env.ts\nmultiTenancy: {\n  headerName: 'x-tenant-id',\n  roleHierarchy: { member: 1, manager: 2, owner: 3 },\n  adminBypass: true,\n}\n\n// Usage in resolvers\n@Roles(DefaultHR.MANAGER)\nasync updateProject(@CurrentTenant() tenantId: string) { ... }\n```\n\n- **Membership validation** — `CoreTenantGuard` validates membership on every request\n- **Hierarchy roles** — Level comparison (higher includes lower), custom via `createHierarchyRoles()`\n- **Automatic data isolation** — Mongoose tenant plugin filters all queries by tenant context\n- **Defense-in-depth** — Guard validation + Mongoose plugin Safety Net combination\n- **Multi-membership** — Users can belong to multiple tenants with different roles\n- **Status management** — ACTIVE, INVITED, SUSPENDED membership states\n- **`@SkipTenantCheck()`** — Opt out per endpoint\n- **`@CurrentTenant()`** — Parameter decorator for validated tenant ID\n\n## Scalability\n\nThe architecture is designed for horizontal scalability:\n\n- **Stateless request handling** — No server-side session state required (JWT or BetterAuth sessions in MongoDB)\n- **Request-scoped isolation** — `AsyncLocalStorage`-based `RequestContext` ensures safe concurrent request processing without shared mutable state\n- **Distributed migration locking** — MongoDB-based distributed locks via `synchronizedMigration()` for safe multi-instance deployments\n- **Query complexity analysis** — Configurable complexity limits prevent expensive GraphQL queries from consuming excessive resources\n- **Connection pooling** — Managed transparently via Mongoose/MongoDB driver\n- **Configurable MongoDB** — Support for replica sets and connection options via `mongoose.uri` configuration\n\n## External System Integration\n\n### Authentication Providers\n\nBetterAuth supports OAuth integration with external identity providers (Google, GitHub, Apple, Discord, and more) via the `socialProviders` configuration.\n\n### SCIM Support\n\nBuilt-in [SCIM](http://www.simplecloud.info/) (System for Cross-domain Identity Management) filter parsing and MongoDB query conversion for enterprise identity management:\n\n```typescript\nscimToMongo('userName eq \"Joe\" and emails[type eq \"work\"]')\n// → MongoDB: { $and: [{ userName: 'Joe' }, { emails: { $elemMatch: { type: 'work' } } }] }\n```\n\nSupported operators: `eq`, `co`, `sw`, `ew`, `gt`, `ge`, `lt`, `le`, `pr`, `aco`, `and`, `or`.\n\n### Email Providers\n\nPluggable email provider abstraction with support for:\n- **Mailjet** — API-based transactional email\n- **Brevo** — API-based transactional email (formerly Sendinblue)\n- **SMTP** — Standard SMTP via Nodemailer\n\nAll providers use the same `EmailService` interface with EJS template engine and locale-aware template resolution.\n\n### Extensibility\n\nThe Module Inheritance Pattern ensures any core module can be extended to integrate with external systems — override service methods to add API calls, event publishing, webhook dispatching, or data synchronization without modifying the framework. See also [Webhook Support](#webhook-support).\n\n## Core Modules\n\n| Module | Purpose |\n|--------|---------|\n| **Auth** | Legacy JWT authentication with Passport strategies |\n| **BetterAuth** | Modern auth (2FA, Passkey, Social, sessions, lifecycle hooks) |\n| **User** | User management, profile, roles, verification |\n| **Tenant** | Multi-tenancy with membership and hierarchy roles |\n| **File** | File upload/download with MongoDB GridFS |\n| **Tus** | Resumable file uploads via [tus.io](https://tus.io/) protocol (up to 50 GB) |\n| **ErrorCode** | Centralized error codes with unique identifiers |\n| **HealthCheck** | REST (`/health`) and GraphQL health monitoring |\n| **Migrate** | MongoDB migration system with distributed locking for cluster deployments |\n| **Permissions** | Security audit dashboard (HTML, JSON, Markdown reports) |\n| **SystemSetup** | Initial admin creation for fresh deployments |\n\n### CrudService\n\nAbstract base service providing a complete CRUD pipeline with built-in security:\n\n```typescript\nexport class ProjectService extends CrudService\u003cProject\u003e {\n  // Inherits: find, findOne, create, update, delete\n  // With: input validation, field selection, security checks, population\n}\n```\n\n**Advanced querying** with comparison operators (`eq`, `ne`, `gt`, `in`, `contains`, `regex`, ...), logical operators (`AND`, `OR`), pagination, sorting, and GraphQL-driven population.\n\n### Security Layers\n\nDefense-in-depth security architecture with three layers:\n\n**Layer 1: Guards \u0026 Middleware**\n- `@Roles()` — Method-level authorization (includes JWT auth automatically)\n- `@Restricted()` — Field-level access control with process type support (INPUT/OUTPUT)\n- System roles — `S_USER`, `S_VERIFIED`, `S_CREATOR`, `S_SELF`, `S_EVERYONE`, `S_NO_ONE`\n\n**Layer 2: CrudService Pipeline**\n- Input validation — MapAndValidatePipe with whitelist checking\n- `@UnifiedField()` — Single decorator for GraphQL, Swagger, and validation\n- `securityCheck()` — Resource-level security on model instances\n\n**Layer 3: Mongoose Plugins (Safety Net)**\n- Password Plugin — Automatic BCrypt hashing\n- Role Guard Plugin — Prevents unauthorized role escalation at DB level\n- Audit Fields Plugin — Automatic `createdBy`/`updatedBy` tracking\n- Tenant Isolation Plugin — Automatic tenant filtering\n\n**Interceptor Chain:**\n- ResponseModelInterceptor — Plain objects to CoreModel conversion\n- TranslateResponseInterceptor — Multi-language support via `Accept-Language`\n- CheckSecurityInterceptor — Executes `securityCheck()` and removes secret fields\n- CheckResponseInterceptor — Enforces `@Restricted()` field-level filtering\n\n### Email \u0026 Templates\n\nMulti-provider email service (Mailjet, Brevo, SMTP) with EJS template engine and locale-aware template resolution.\n\n## Configuration\n\nConfiguration is managed via `src/config.env.ts` with environment-based profiles (development, local, production):\n\n```typescript\nexport const config = {\n  local: {\n    port: 3000,\n    graphQl: { driver: 'apollo' },\n    mongoose: { uri: 'mongodb://localhost/my-app' },\n    betterAuth: { secret: 'my-secret', jwt: true, twoFactor: true },\n    multiTenancy: { roleHierarchy: { member: 1, manager: 2, owner: 3 } },\n  },\n};\n```\n\n### Configuration Patterns\n\n- **Presence implies enabled**: `rateLimit: {}` enables with defaults, `undefined` stays disabled\n- **Boolean shorthand**: `jwt: true` enables with defaults, `{ expiresIn: '1h' }` customizes\n\n### Environment Variables\n\nThree methods to override configuration:\n\n1. **Direct** — `process.env.PORT` in `config.env.ts`\n2. **JSON** — `NEST_SERVER_CONFIG` environment variable (deep merge)\n3. **Prefixed** — `NSC__EMAIL__DEFAULT_SENDER__NAME` for `email.defaultSender.name`\n\n## Development\n\n**Requirements:** Node.js \u003e= 20, MongoDB, pnpm\n\n```bash\n# Install dependencies\npnpm install\n\n# Start in development mode\npnpm run start:dev\n\n# Run tests (Vitest E2E)\npnpm test\n\n# Run tests with coverage\npnpm run vitest:cov\n\n# Lint (oxlint) \u0026 format (oxfmt)\npnpm run lint\npnpm run format\n\n# Build\npnpm run build\n\n# Generate documentation\npnpm run docs\n```\n\n### Debugging as package\n\nLink into a consuming project for local development:\n\n```bash\n# In nest-server\npnpm run watch\n\n# In your project\npnpm run link:nest-server     # pnpm link /path/to/nest-server\npnpm run unlink:nest-server   # pnpm unlink @lenne.tech/nest-server \u0026\u0026 pnpm install\n```\n\n### Versioning\n\n`MAJOR.MINOR.PATCH` — MAJOR mirrors NestJS version, MINOR = breaking changes, PATCH = non-breaking improvements.\n\n## Documentation\n\n- [Request Lifecycle](docs/REQUEST-LIFECYCLE.md) — Complete request pipeline, security architecture, interceptor chain\n- [Migration Guides](migration-guides/) — Version upgrade instructions\n- [Starter Project](https://github.com/lenneTech/nest-server-starter) — Reference implementation\n- [CLI](https://github.com/lenneTech/cli) — Code generation tools\n- [NestJS Documentation](https://docs.nestjs.com/) — Framework docs\n\n## Thanks\n\nMany thanks to the developers of [NestJS](https://github.com/nestjs/nest)\nand all the developers whose packages are used here.\n\n## License\n\nMIT - see [LICENSE](/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flennetech%2Fnest-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flennetech%2Fnest-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flennetech%2Fnest-server/lists"}