# BACKEND_INVENTORY.yml - ERP Core # Inventario canonico de objetos backend # Ubicacion Canonica: orchestration/inventarios/ # Ultima actualizacion: 2025-12-05 version: "1.0" project: erp-core updated_at: "2025-12-05" updated_by: Requirements-Analyst # ============================================================================= # CONFIGURACION DEL STACK # ============================================================================= stack: runtime: Node.js 20+ framework: NestJS 10.x language: TypeScript 5.3+ orm: TypeORM 0.3.17 validation: class-validator + class-transformer documentation: Swagger/OpenAPI # ============================================================================= # RESUMEN # ============================================================================= summary: total_modules: 19 total_services: 45 total_controllers: 38 total_endpoints: 180 total_entities: 48 total_dtos: 85 total_guards: 12 total_decorators: 15 implemented: 0 documented: 4 # ============================================================================= # MODULOS # ============================================================================= modules: # --------------------------------------------------------------------------- # MGN-001: AUTH # --------------------------------------------------------------------------- - id: MGN-001 name: auth path: apps/backend/src/modules/auth/ status: documented rf: [RF-AUTH-001, RF-AUTH-002, RF-AUTH-003, RF-AUTH-004, RF-AUTH-005, RF-AUTH-006] entities: - name: UserAuth file: entities/user-auth.entity.ts table: core_auth.users_auth rf: RF-AUTH-001 - name: Session file: entities/session.entity.ts table: core_auth.sessions rf: RF-AUTH-002 - name: RefreshToken file: entities/refresh-token.entity.ts table: core_auth.refresh_tokens rf: RF-AUTH-002 - name: PasswordReset file: entities/password-reset.entity.ts table: core_auth.password_resets rf: RF-AUTH-003 - name: LoginAttempt file: entities/login-attempt.entity.ts table: core_auth.login_attempts rf: RF-AUTH-004 - name: OAuthAccount file: entities/oauth-account.entity.ts table: core_auth.oauth_accounts rf: RF-AUTH-005 services: - name: AuthService file: auth.service.ts rf: [RF-AUTH-001, RF-AUTH-006] methods: - {name: login, params: [LoginDto], returns: TokenResponseDto} - {name: logout, params: [userId], returns: void} - {name: logoutAll, params: [userId], returns: void} - {name: validateUser, params: [email, password], returns: UserAuth} - {name: getProfile, params: [userId], returns: UserProfileDto} - name: TokenService file: token.service.ts rf: [RF-AUTH-002] methods: - {name: generateAccessToken, params: [payload], returns: string} - {name: generateRefreshToken, params: [userId], returns: string} - {name: refreshTokens, params: [refreshToken], returns: TokenResponseDto} - {name: revokeRefreshToken, params: [tokenId], returns: void} - {name: validateAccessToken, params: [token], returns: JwtPayload} - name: PasswordService file: password.service.ts rf: [RF-AUTH-003] methods: - {name: requestPasswordReset, params: [email], returns: void} - {name: resetPassword, params: [token, newPassword], returns: void} - {name: validateResetToken, params: [token], returns: boolean} - name: OAuthService file: oauth.service.ts rf: [RF-AUTH-005] methods: - {name: initiateOAuth, params: [provider], returns: string} - {name: handleCallback, params: [provider, code], returns: TokenResponseDto} - {name: linkAccount, params: [userId, provider, data], returns: void} controllers: - name: AuthController file: auth.controller.ts prefix: /api/v1/auth endpoints: - {method: POST, path: /login, handler: login, rf: RF-AUTH-001, auth: false} - {method: POST, path: /logout, handler: logout, rf: RF-AUTH-006, auth: true} - {method: POST, path: /refresh, handler: refresh, rf: RF-AUTH-002, auth: false} - {method: POST, path: /forgot-password, handler: forgotPassword, rf: RF-AUTH-003, auth: false} - {method: POST, path: /reset-password, handler: resetPassword, rf: RF-AUTH-003, auth: false} - {method: GET, path: /me, handler: getProfile, rf: RF-AUTH-001, auth: true} - {method: GET, path: /oauth/:provider, handler: initiateOAuth, rf: RF-AUTH-005, auth: false} dtos: - {name: LoginDto, file: dto/login.dto.ts, type: request} - {name: TokenResponseDto, file: dto/token-response.dto.ts, type: response} - {name: RefreshTokenDto, file: dto/refresh-token.dto.ts, type: request} - {name: ForgotPasswordDto, file: dto/forgot-password.dto.ts, type: request} - {name: ResetPasswordDto, file: dto/reset-password.dto.ts, type: request} - {name: UserProfileDto, file: dto/user-profile.dto.ts, type: response} guards: - name: JwtAuthGuard file: guards/jwt-auth.guard.ts rf: RF-AUTH-002 description: Valida JWT en header Authorization - name: RefreshTokenGuard file: guards/refresh-token.guard.ts rf: RF-AUTH-002 description: Valida refresh token decorators: - name: CurrentUser file: decorators/current-user.decorator.ts usage: "@CurrentUser() user: UserAuth" - name: Public file: decorators/public.decorator.ts usage: "@Public()" strategies: - name: JwtStrategy file: strategies/jwt.strategy.ts rf: RF-AUTH-002 - name: LocalStrategy file: strategies/local.strategy.ts rf: RF-AUTH-001 # --------------------------------------------------------------------------- # MGN-002: USERS # --------------------------------------------------------------------------- - id: MGN-002 name: users path: apps/backend/src/modules/users/ status: documented rf: [RF-USERS-001, RF-USERS-002, RF-USERS-003, RF-USERS-004, RF-USERS-005] entities: - name: User file: entities/user.entity.ts table: core_users.users rf: RF-USERS-001 - name: UserProfile file: entities/user-profile.entity.ts table: core_users.user_profiles rf: RF-USERS-002 - name: UserPreferences file: entities/user-preferences.entity.ts table: core_users.user_preferences rf: RF-USERS-003 services: - name: UsersService file: users.service.ts rf: [RF-USERS-001, RF-USERS-004, RF-USERS-005] methods: - {name: create, params: [CreateUserDto], returns: User} - {name: findAll, params: [filters, pagination], returns: "PaginatedResult"} - {name: findOne, params: [id], returns: User} - {name: update, params: [id, UpdateUserDto], returns: User} - {name: remove, params: [id], returns: void} - {name: activate, params: [id], returns: User} - {name: deactivate, params: [id], returns: User} - {name: search, params: [query], returns: "User[]"} - name: ProfileService file: profile.service.ts rf: [RF-USERS-002] methods: - {name: getProfile, params: [userId], returns: UserProfile} - {name: updateProfile, params: [userId, dto], returns: UserProfile} - {name: uploadAvatar, params: [userId, file], returns: string} - name: PreferencesService file: preferences.service.ts rf: [RF-USERS-003] methods: - {name: getPreferences, params: [userId], returns: UserPreferences} - {name: updatePreferences, params: [userId, dto], returns: UserPreferences} controllers: - name: UsersController file: users.controller.ts prefix: /api/v1/users endpoints: - {method: GET, path: /, handler: findAll, rf: RF-USERS-001} - {method: GET, path: /:id, handler: findOne, rf: RF-USERS-001} - {method: POST, path: /, handler: create, rf: RF-USERS-001} - {method: PATCH, path: /:id, handler: update, rf: RF-USERS-001} - {method: DELETE, path: /:id, handler: remove, rf: RF-USERS-001} - {method: GET, path: /:id/profile, handler: getProfile, rf: RF-USERS-002} - {method: PATCH, path: /:id/profile, handler: updateProfile, rf: RF-USERS-002} - {method: POST, path: /:id/avatar, handler: uploadAvatar, rf: RF-USERS-002} - {method: GET, path: /:id/preferences, handler: getPreferences, rf: RF-USERS-003} - {method: PATCH, path: /:id/preferences, handler: updatePreferences, rf: RF-USERS-003} - {method: POST, path: /:id/activate, handler: activate, rf: RF-USERS-004} - {method: POST, path: /:id/deactivate, handler: deactivate, rf: RF-USERS-004} - {method: GET, path: /search, handler: search, rf: RF-USERS-005} dtos: - {name: CreateUserDto, file: dto/create-user.dto.ts, type: request} - {name: UpdateUserDto, file: dto/update-user.dto.ts, type: request} - {name: UserFilterDto, file: dto/user-filter.dto.ts, type: request} - {name: UserResponseDto, file: dto/user-response.dto.ts, type: response} - {name: UpdateProfileDto, file: dto/update-profile.dto.ts, type: request} - {name: UpdatePreferencesDto, file: dto/update-preferences.dto.ts, type: request} # --------------------------------------------------------------------------- # MGN-003: ROLES # --------------------------------------------------------------------------- - id: MGN-003 name: roles path: apps/backend/src/modules/roles/ status: documented rf: [RF-RBAC-001, RF-RBAC-002, RF-RBAC-003, RF-RBAC-004, RF-RBAC-005] entities: - name: Role file: entities/role.entity.ts table: core_rbac.roles rf: RF-RBAC-001 - name: Permission file: entities/permission.entity.ts table: core_rbac.permissions rf: RF-RBAC-002 - name: RolePermission file: entities/role-permission.entity.ts table: core_rbac.role_permissions rf: RF-RBAC-002 - name: UserRole file: entities/user-role.entity.ts table: core_rbac.user_roles rf: RF-RBAC-003 services: - name: RolesService file: roles.service.ts rf: [RF-RBAC-001, RF-RBAC-005] methods: - {name: create, params: [CreateRoleDto], returns: Role} - {name: findAll, params: [tenantId], returns: "Role[]"} - {name: findOne, params: [id], returns: Role} - {name: update, params: [id, UpdateRoleDto], returns: Role} - {name: remove, params: [id], returns: void} - {name: getSystemRoles, params: [], returns: "Role[]"} - name: PermissionsService file: permissions.service.ts rf: [RF-RBAC-002, RF-RBAC-004] methods: - {name: findAll, params: [], returns: "Permission[]"} - {name: findByModule, params: [module], returns: "Permission[]"} - {name: assignToRole, params: [roleId, permissionId], returns: void} - {name: removeFromRole, params: [roleId, permissionId], returns: void} - {name: getUserPermissions, params: [userId], returns: "Permission[]"} - {name: hasPermission, params: [userId, module, action, resource], returns: boolean} - name: UserRolesService file: user-roles.service.ts rf: [RF-RBAC-003] methods: - {name: assignRole, params: [userId, roleId], returns: void} - {name: removeRole, params: [userId, roleId], returns: void} - {name: getUserRoles, params: [userId], returns: "Role[]"} controllers: - name: RolesController file: roles.controller.ts prefix: /api/v1/roles endpoints: - {method: GET, path: /, handler: findAll, rf: RF-RBAC-001} - {method: POST, path: /, handler: create, rf: RF-RBAC-001} - {method: GET, path: /:id, handler: findOne, rf: RF-RBAC-001} - {method: PATCH, path: /:id, handler: update, rf: RF-RBAC-001} - {method: DELETE, path: /:id, handler: remove, rf: RF-RBAC-001} - {method: GET, path: /:id/permissions, handler: getRolePermissions, rf: RF-RBAC-002} - {method: POST, path: /:id/permissions, handler: assignPermission, rf: RF-RBAC-002} - {method: DELETE, path: /:id/permissions/:permissionId, handler: removePermission, rf: RF-RBAC-002} - name: PermissionsController file: permissions.controller.ts prefix: /api/v1/permissions endpoints: - {method: GET, path: /, handler: findAll, rf: RF-RBAC-002} - {method: GET, path: /modules, handler: getModules, rf: RF-RBAC-002} guards: - name: RolesGuard file: guards/roles.guard.ts rf: RF-RBAC-004 description: Verifica roles requeridos - name: PermissionsGuard file: guards/permissions.guard.ts rf: RF-RBAC-004 description: Verifica permisos requeridos decorators: - name: Roles file: decorators/roles.decorator.ts usage: "@Roles('admin', 'manager')" - name: Permissions file: decorators/permissions.decorator.ts usage: "@Permissions('users:read:all')" - name: RequirePermission file: decorators/require-permission.decorator.ts usage: "@RequirePermission('users', 'write', 'all')" # --------------------------------------------------------------------------- # MGN-004: TENANTS # --------------------------------------------------------------------------- - id: MGN-004 name: tenants path: apps/backend/src/modules/tenants/ status: documented rf: [RF-TENANTS-001, RF-TENANTS-002, RF-TENANTS-003, RF-TENANTS-004, RF-TENANTS-005] entities: - name: Tenant file: entities/tenant.entity.ts table: core_tenants.tenants rf: RF-TENANTS-001 - name: TenantSettings file: entities/tenant-settings.entity.ts table: core_tenants.tenant_settings rf: RF-TENANTS-002 - name: Plan file: entities/plan.entity.ts table: core_tenants.plans rf: RF-TENANTS-003 - name: Subscription file: entities/subscription.entity.ts table: core_tenants.subscriptions rf: RF-TENANTS-003 services: - name: TenantsService file: tenants.service.ts rf: [RF-TENANTS-001, RF-TENANTS-005] methods: - {name: create, params: [CreateTenantDto], returns: Tenant} - {name: findAll, params: [], returns: "Tenant[]"} - {name: findOne, params: [id], returns: Tenant} - {name: findBySlug, params: [slug], returns: Tenant} - {name: update, params: [id, UpdateTenantDto], returns: Tenant} - {name: remove, params: [id], returns: void} - {name: onboard, params: [OnboardDto], returns: Tenant} - name: TenantSettingsService file: tenant-settings.service.ts rf: [RF-TENANTS-002] methods: - {name: getSettings, params: [tenantId], returns: TenantSettings} - {name: updateSettings, params: [tenantId, dto], returns: TenantSettings} - name: PlansService file: plans.service.ts rf: [RF-TENANTS-003] methods: - {name: findAll, params: [], returns: "Plan[]"} - {name: findOne, params: [id], returns: Plan} - name: SubscriptionsService file: subscriptions.service.ts rf: [RF-TENANTS-003] methods: - {name: create, params: [tenantId, planId], returns: Subscription} - {name: getCurrentSubscription, params: [tenantId], returns: Subscription} - {name: changePlan, params: [subscriptionId, planId], returns: Subscription} - {name: cancel, params: [subscriptionId], returns: void} middleware: - name: TenantMiddleware file: middleware/tenant.middleware.ts rf: RF-TENANTS-004 description: Extrae tenant_id y establece contexto RLS guards: - name: TenantGuard file: guards/tenant.guard.ts rf: RF-TENANTS-004 description: Verifica tenant activo - name: SubscriptionGuard file: guards/subscription.guard.ts rf: RF-TENANTS-003 description: Verifica suscripcion activa controllers: - name: TenantsController file: tenants.controller.ts prefix: /api/v1/tenants endpoints: - {method: GET, path: /, handler: findAll, rf: RF-TENANTS-001} - {method: POST, path: /, handler: create, rf: RF-TENANTS-001} - {method: GET, path: /:id, handler: findOne, rf: RF-TENANTS-001} - {method: PATCH, path: /:id, handler: update, rf: RF-TENANTS-001} - {method: GET, path: /current, handler: getCurrent, rf: RF-TENANTS-001} - {method: GET, path: /current/settings, handler: getSettings, rf: RF-TENANTS-002} - {method: PATCH, path: /current/settings, handler: updateSettings, rf: RF-TENANTS-002} - name: PlansController file: plans.controller.ts prefix: /api/v1/plans endpoints: - {method: GET, path: /, handler: findAll, rf: RF-TENANTS-003} - {method: GET, path: /:id, handler: findOne, rf: RF-TENANTS-003} - name: SubscriptionsController file: subscriptions.controller.ts prefix: /api/v1/subscriptions endpoints: - {method: GET, path: /current, handler: getCurrent, rf: RF-TENANTS-003} - {method: POST, path: /, handler: create, rf: RF-TENANTS-003} - {method: PATCH, path: /current/plan, handler: changePlan, rf: RF-TENANTS-003} - {method: POST, path: /current/cancel, handler: cancel, rf: RF-TENANTS-003} decorators: - name: CurrentTenant file: decorators/current-tenant.decorator.ts usage: "@CurrentTenant() tenant: Tenant" # ============================================================================= # SHARED / COMMON # ============================================================================= shared: path: apps/backend/src/shared/ utils: - {name: pagination.util.ts, description: Helpers de paginacion} - {name: hash.util.ts, description: Funciones de hash} - {name: date.util.ts, description: Manipulacion de fechas} types: - {name: pagination.types.ts, description: Tipos de paginacion} - {name: api-response.types.ts, description: Tipos de respuesta API} constants: - {name: roles.constants.ts, description: Constantes de roles} - {name: permissions.constants.ts, description: Lista de permisos} interceptors: - {name: logging.interceptor.ts, description: Log de requests} - {name: transform.interceptor.ts, description: Transformacion de respuestas} filters: - {name: http-exception.filter.ts, description: Manejo de excepciones HTTP} - {name: validation.filter.ts, description: Errores de validacion} pipes: - {name: validation.pipe.ts, description: Validacion global} - {name: parse-uuid.pipe.ts, description: Parsing de UUIDs} # ============================================================================= # CONFIGURACION # ============================================================================= config: path: apps/backend/src/config/ files: - {name: database.config.ts, description: Conexion PostgreSQL} - {name: jwt.config.ts, description: Configuracion JWT} - {name: cors.config.ts, description: Configuracion CORS} - {name: app.config.ts, description: Configuracion general} - {name: redis.config.ts, description: Conexion Redis} - {name: mail.config.ts, description: Configuracion email} # ============================================================================= # DEPENDENCIAS # ============================================================================= dependencies: production: - "@nestjs/common": "^10.0.0" - "@nestjs/core": "^10.0.0" - "@nestjs/platform-express": "^10.0.0" - "@nestjs/typeorm": "^10.0.0" - "@nestjs/jwt": "^10.0.0" - "@nestjs/passport": "^10.0.0" - "@nestjs/swagger": "^7.0.0" - "typeorm": "^0.3.17" - "pg": "^8.11.0" - "bcryptjs": "^2.4.3" - "passport": "^0.7.0" - "passport-jwt": "^4.0.1" - "passport-local": "^1.0.0" - "class-validator": "^0.14.0" - "class-transformer": "^0.5.1" - "uuid": "^9.0.0" development: - "typescript": "^5.3.0" - "@nestjs/cli": "^10.0.0" - "@nestjs/testing": "^10.0.0" - "jest": "^29.0.0" - "supertest": "^6.3.0" - "@types/node": "^20.0.0" # ============================================================================= # TESTS # ============================================================================= tests: framework: Jest target_coverage: 80% structure: unit: "src/**/__tests__/*.spec.ts" integration: "test/**/*.e2e-spec.ts" # ============================================================================= # HISTORIAL # ============================================================================= history: - date: "2025-12-05" action: "Reestructuracion completa siguiendo filosofia GAMILIT" author: Requirements-Analyst changes: - "Documentados 4 modulos foundation completos" - "Agregada trazabilidad RF por servicio y endpoint" - "Documentados DTOs, guards, decorators"