Pular para o conteúdo principal

Tenant Bypass Exceptions

This document catalogs all locations in the codebase where data access intentionally bypasses the automatic tenantId scoping provided by TenantAwareCrudService. Every entry below has been reviewed and classified.

Rule: All other data access in services extending TenantAwareCrudService MUST use inherited base class methods (this.find(), this.save(), this.delete(), this.findOneByIdString(), etc.) which automatically scope by tenant.


Category 1 — Cross-Tenant by Design (P2)

These services intentionally operate across tenants for authentication, authorization, or global configuration.

ServiceFileMethodsJustification
UserServicepackages/core/src/lib/user/user.service.tsfindOneByEmail, checkIfExistsEmail, checkIfExists, checkIfExistsThirdPartyIdEntity, getUserByEmail, getUserByThirdPartyId, createUser, getAdminUsers, updateRefreshToken, removeRefreshToken, markLoginUser lookups are cross-tenant for login, SSO, and third-party auth. A user may exist in multiple tenants; email uniqueness and authentication must work globally.
RoleServicepackages/core/src/lib/role/role.service.tscreateQueryBuilder for role lookupsRoles can be system-level (isSystem: true) and shared across tenants. Role lookup during auth must work before tenant context is established.
RolePermissionServicepackages/core/src/lib/role-permission/role-permission.service.tsfind, save, createQueryBuilderPermission seed operations and system-level permission checks operate across tenants. Guards check permissions before tenant context is fully resolved.
TenantSettingServicepackages/core/src/lib/tenant/tenant-setting/tenant-setting.service.tsfind, findBy, save (multiple methods)Explicitly queries both global settings (tenantId: null) and tenant-specific settings, then merges them. The where clauses manually include tenantId where appropriate.
SocialAccountServicepackages/core/src/lib/auth/social-account/social-account.service.tsfindOneBy, saveSocial account linking (Google, GitHub, etc.) requires cross-tenant lookup to prevent duplicate social accounts and to find existing users across tenants during SSO login.
AccountingTemplateServicepackages/core/src/lib/accounting-template/accounting-template.service.tsfindOneBy, saveSystem-level accounting templates are seeded with tenantId: null and must be accessible globally for initial tenant setup.
AvailabilitySlotsServicepackages/core/src/lib/availability-slots/availability-slots.service.tscreateQueryBuilderUses createQueryBuilder with manual tenantId filter in the query. Complex join queries that cannot be expressed via base class methods.

Category 2 — Manual Tenant Filter via createQueryBuilder (P1)

These services use this.typeOrmRepository.createQueryBuilder() with manual .andWhere('tenantId = :tenantId') filters. They are not security vulnerabilities but bypass the automatic tenant scoping pattern. They use createQueryBuilder because they require complex joins, subqueries, or aggregation not expressible via FindManyOptions.

ServiceFile# of QB callsReason for createQueryBuilder
TimeLogServicepackages/core/src/lib/time-tracking/time-log/time-log.service.ts~10Complex time log aggregation, date range queries, employee joins
TimeSheetServicepackages/core/src/lib/time-tracking/timesheet/timesheet.service.ts2Timesheet approval workflows with status filtering
TimeSlotServicepackages/core/src/lib/time-tracking/time-slot/time-slot.service.ts1Time slot aggregation with screenshot/activity joins
ActivityServicepackages/core/src/lib/time-tracking/activity/activity.service.ts1Activity aggregation with time slot joins
ScreenshotServicepackages/core/src/lib/time-tracking/screenshot/screenshot.service.ts1Screenshot deletion with employee permission join
TaskServicepackages/core/src/lib/tasks/task.service.ts~5Complex task queries with sprint, project, team filters
DailyPlanServicepackages/core/src/lib/tasks/daily-plan/daily-plan.service.ts~3Daily plan queries with task/employee joins
OrganizationTeamServicepackages/core/src/lib/organization-team/organization-team.service.ts1Team queries with member/project joins
OrganizationProjectServicepackages/core/src/lib/organization-project/organization-project.service.ts2Project queries with member/repository joins
OrganizationTeamJoinRequestServicepackages/core/src/lib/organization-team-join-request/organization-team-join-request.service.ts1Join request with team/employee validation
OrganizationProjectModuleServicepackages/core/src/lib/organization-project-module/organization-project-module.service.ts1Module queries with project joins
OrganizationContactServicepackages/core/src/lib/organization-contact/organization-contact.service.ts1Contact queries with member joins
TimeOffRequestServicepackages/core/src/lib/time-off-request/time-off-request.service.ts2Time-off queries with approval workflow joins
EquipmentSharingServicepackages/core/src/lib/equipment-sharing/equipment-sharing.service.ts1Equipment sharing with approval joins
RequestApprovalServicepackages/core/src/lib/request-approval/request-approval.service.ts1Approval queries with policy joins
InviteServicepackages/core/src/lib/invite/invite.service.ts1Invite validation queries
EstimateEmailServicepackages/core/src/lib/estimate-email/estimate-email.service.ts0Uses findOneOrFail with manual tenantId in where
PaymentServicepackages/core/src/lib/payment/payment.service.ts1Payment aggregation with invoice joins
ExpenseServicepackages/core/src/lib/expense/expense.service.ts1Expense queries with category/vendor joins
InvoiceServicepackages/core/src/lib/invoice/invoice.service.ts1Invoice queries with item/payment joins
CandidateServicepackages/core/src/lib/candidate/candidate.service.ts1Candidate queries with interview joins
EmployeeServicepackages/core/src/lib/employee/employee.service.ts1Employee pagination with complex filters
TagServicepackages/core/src/lib/tags/tag.service.ts1Tag queries with entity type joins
ReportServicepackages/core/src/lib/reports/report.service.ts1Report queries with organization joins
EmailHistoryServicepackages/core/src/lib/email-history/email-history.service.ts1Email history with template joins
EmailResetServicepackages/core/src/lib/email-reset/email-reset.service.ts1Email reset token queries
EmailTemplateServicepackages/core/src/lib/email-template/email-template.service.ts1Template queries with language joins

Category 3 — Plugin Services (P1/P2)

ServiceFileClassificationNotes
JobPresetServicepackages/plugins/job-search/src/lib/employee-job-preset/job-preset.service.tsP1Uses createQueryBuilder with manual tenant filter for complex preset/criteria joins
PluginSubscriptionPlanServicepackages/plugins/registry/src/lib/domain/services/plugin-subscription-plan.service.tsP2Plugin subscription plans are global marketplace entities; find, findOne, update, delete operate across tenants for plan management

Category 4 — Base Class Internal Usage

ServiceFileNotes
CrudServicepackages/core/src/lib/core/crud/crud.service.tsThis IS the base class. Direct repository calls here are the internal implementation that all tenant-aware methods delegate to. Not a bypass.

Maintenance Guidelines

  1. New services extending TenantAwareCrudService must use base class methods unless they fall into Category 1 or 2 above
  2. Any new createQueryBuilder usage must include .andWhere('tenantId = :tenantId', { tenantId }) and be documented here
  3. Any new cross-tenant operation must be added to Category 1 with justification
  4. Periodic audit: run grep -r 'this.typeOrmRepository\.' --include='*.service.ts' and verify all hits are documented