Skip to content

Comments

Apps (Stage)#9502

Merged
evereq merged 5 commits intostage-appsfrom
stage
Feb 23, 2026
Merged

Apps (Stage)#9502
evereq merged 5 commits intostage-appsfrom
stage

Conversation

@evereq
Copy link
Member

@evereq evereq commented Feb 23, 2026

PR

Please note: we will close your PR without comment if you do not check the boxes above and provide ALL requested information.



Summary by cubic

Standardized CRUD and tenant-aware operations across core services for safer, consistent data access and bulk operations. Also improved Windows CI stability, tightened password rules, and fixed interview feedback behavior.

  • Refactors

    • Added createMany/saveMany helpers and replaced direct repository calls with base CRUD methods (save, saveMany, find, delete).
    • Enforced tenant scoping and safer deletes/soft-deletes across services (time-tracking, products, tasks, org/team, KB, etc.).
    • Time slots: pass tenantId, validate employee/organization, and clamp invalid metrics; cleaner bulk create/update paths.
  • Bug Fixes

    • Allow adding interview feedback only for past interviews; cleaned up Users page template.
    • Increased minimum password length to 8 (registration and password reset).
    • Stabilized Windows GitHub Actions by setting $ErrorActionPreference during cleanup; fixed various lookups and in-use checks (e.g., ImageAsset).

Written for commit b921136. Summary will update on new commits.

evereq and others added 5 commits February 23, 2026 20:33
* fix: use super class methods

* fix: more use of super

* fix: more use of super

* fix: use ID

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* Update packages/core/src/lib/product/commands/handlers/product.delete.handler.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* Apply suggestion from @cubic-dev-ai[bot]

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* Apply suggestion from @cubic-dev-ai[bot]

* Apply suggestion from @cubic-dev-ai[bot]

* Apply suggestion from @cubic-dev-ai[bot]

* Apply suggestion from @cubic-dev-ai[bot]

* fix(core): API build for prod mode

* Apply suggestion from @cubic-dev-ai[bot]

* Apply suggestion from @cubic-dev-ai[bot]

* Apply suggestion from @cubic-dev-ai[bot]

---------

Co-authored-by: Rahul R. <rahulrathore576@gmail.com>
Co-authored-by: Rahul R. <41804588+rahul-rocket@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers

* fix(build): apply AI suggestion by bot agent reviewers
@evereq evereq changed the title RElease Apps (Stage) Feb 23, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch stage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@evereq evereq merged commit a1220f1 into stage-apps Feb 23, 2026
15 of 17 checks passed
@sonarqubecloud
Copy link

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 23, 2026

Greptile Summary

This PR introduces a major refactoring to improve database operation performance by adding bulk operation methods (createMany(), saveMany(), deleteMany()) to the CRUD service layer, then migrating 96 files across the codebase to use these new methods.

Key Changes:

  • Added bulk operation methods to CrudService and TenantAwareCrudService base classes with proper MikroORM and TypeORM implementations
  • Updated ICrudService interface to include new bulk method signatures
  • Migrated services, handlers, and commands throughout the codebase to replace loop-based operations with bulk operations
  • Enhanced tenant isolation in RegisterAuthorizationGuard by adding organizationId validation
  • Improved broadcast service with better tenant/organization scoping
  • Optimized time slot correction handler to use selective field queries and bulk updates
  • Refactored product deletion handler to use parallel operations and bulk deletions
  • Added workflow error handling improvements for Windows builds
  • Minor formatting and code style improvements

PR Template Issue:
The PR template checklist is not completed (boxes are not checked and explanation is missing), which violates the contributing guidelines per custom rule 90653f25-bd57-4517-ae57-772fe2013d9c. The PR description only contains the template itself without filling in the required information.

Title Issue:
The PR title "RElease" contains a typo and should be "Release".

Confidence Score: 5/5

  • This PR is safe to merge - it's a well-executed performance optimization refactoring with consistent patterns
  • The refactoring is systematic and follows consistent patterns throughout. The bulk operation methods properly handle both ORMs (TypeORM and MikroORM), include appropriate tenant scoping in TenantAwareCrudService, and the migration from loop-based to bulk operations is applied consistently. The security enhancements (organizationId validation, tenant scoping improvements) strengthen isolation. The changes are primarily internal optimizations that maintain the same external behavior while improving performance. No breaking changes to APIs or logical errors detected.
  • No files require special attention - the refactoring is systematic and well-implemented

Important Files Changed

Filename Overview
packages/core/src/lib/core/crud/crud.service.ts Adds createMany(), saveMany(), and deleteMany() bulk operation methods with MikroORM and TypeORM implementations for improved performance.
packages/core/src/lib/core/crud/tenant-aware-crud.service.ts Extends bulk methods with tenant/employee scoping, improves code readability, adds tenant validation to deleteMany().
packages/core/src/lib/core/crud/icrud.service.ts Updates interface with createMany(), saveMany(), and deleteMany() method signatures to support bulk operations.
packages/core/src/lib/broadcast/broadcast.service.ts Adds organizationId parameter to entity member checks, improves tenant scoping in queries, adds tenantId filtering in team lookups.
packages/core/src/lib/shared/guards/register-authorization.guard.ts Adds organizationId tenant isolation validation, consolidates ORM query patterns, improves error handling to prevent tenant data leaks.
packages/core/src/lib/product/commands/handlers/product.delete.handler.ts Major refactor: uses bulk operations with deleteMany(), processes option groups in parallel, adds calculateAffected() helper.
packages/core/src/lib/time-tracking/time-slot/commands/handlers/schedule-time-slot-entries.handler.ts Optimizes query to select only needed fields, adds tenant/organization scoping, replaces loop-based updates with bulk save.
packages/core/src/lib/organization-team-employee/organization-team-employee.service.ts Refactors to use createMany() and deleteMany() bulk operations, improves transaction handling.

Last reviewed commit: b921136

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

96 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 96 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/core/src/lib/feature/feature-organization.service.ts">

<violation number="1" location="packages/core/src/lib/feature/feature-organization.service.ts:96">
P1: saveMany overwrites each entity’s tenant/tenantId with the current RequestContext tenant. This method builds entries for multiple tenants, so saving with saveMany collapses them all into the current tenant and corrupts tenant associations. Use the raw repository save (or another method that preserves per-entity tenant) here.</violation>
</file>

<file name="packages/core/src/lib/tasks/issue-type/issue-type.service.ts">

<violation number="1" location="packages/core/src/lib/tasks/issue-type/issue-type.service.ts:115">
P1: saveMany overwrites tenant/tenantId with RequestContext.currentTenantId(), so bulkCreateTenantsIssueTypes now ignores the per-tenant values built in issueTypes and creates everything under the current tenant. This breaks multi-tenant seeding.</violation>
</file>

<file name="packages/core/src/lib/tasks/task-status-priority-size.service.ts">

<violation number="1" location="packages/core/src/lib/tasks/task-status-priority-size.service.ts:117">
P2: super.findAll applies tenant scoping and overrides the IsNull() tenant filter in getDefaultEntities, so system defaults (tenantId=null) won’t be returned for authenticated tenants.</violation>
</file>

<file name="packages/core/src/lib/tasks/priorities/priority.service.ts">

<violation number="1" location="packages/core/src/lib/tasks/priorities/priority.service.ts:91">
P1: saveMany overwrites tenant/tenantId with RequestContext.currentTenantId, so bulkCreateTenantsTaskPriorities will persist every priority under the current tenant instead of the per-tenant values built in the loop.</violation>
</file>

<file name="packages/core/src/lib/product-type/product-type.service.ts">

<violation number="1" location="packages/core/src/lib/product-type/product-type.service.ts:62">
P1: The MikroORM fallback path does not enforce `entity.tenantId = tenantId` before saving, unlike the TypeORM path above. This asymmetry can allow an entity with a missing or incorrect `tenantId` to be persisted, breaking tenant isolation.</violation>
</file>

<file name="packages/core/src/lib/product-setting/product-setting.service.ts">

<violation number="1" location="packages/core/src/lib/product-setting/product-setting.service.ts:37">
P2: deleteManySettings always returns the input array instead of the actual delete result, so callers like ProductDeleteHandler will over-count deletions whenever super.deleteMany removes fewer rows than the input size (tenant scoping, missing ids). Return the real DeleteResult/[] or an array that reflects actual deletions.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

}

return await this.typeOrmRepository.save(featureOrganizations);
return await this.saveMany(featureOrganizations);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: saveMany overwrites each entity’s tenant/tenantId with the current RequestContext tenant. This method builds entries for multiple tenants, so saving with saveMany collapses them all into the current tenant and corrupts tenant associations. Use the raw repository save (or another method that preserves per-entity tenant) here.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/lib/feature/feature-organization.service.ts, line 96:

<comment>saveMany overwrites each entity’s tenant/tenantId with the current RequestContext tenant. This method builds entries for multiple tenants, so saving with saveMany collapses them all into the current tenant and corrupts tenant associations. Use the raw repository save (or another method that preserves per-entity tenant) here.</comment>

<file context>
@@ -93,6 +93,6 @@ export class FeatureOrganizationService extends TenantAwareCrudService<FeatureOr
 		}
 
-		return await this.typeOrmRepository.save(featureOrganizations);
+		return await this.saveMany(featureOrganizations);
 	}
 }
</file context>
Fix with Cubic


// Save the created or fetched issue types to the repository and return the result.
return await this.typeOrmRepository.save(issueTypes);
return await this.saveMany(issueTypes);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: saveMany overwrites tenant/tenantId with RequestContext.currentTenantId(), so bulkCreateTenantsIssueTypes now ignores the per-tenant values built in issueTypes and creates everything under the current tenant. This breaks multi-tenant seeding.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/lib/tasks/issue-type/issue-type.service.ts, line 115:

<comment>saveMany overwrites tenant/tenantId with RequestContext.currentTenantId(), so bulkCreateTenantsIssueTypes now ignores the per-tenant values built in issueTypes and creates everything under the current tenant. This breaks multi-tenant seeding.</comment>

<file context>
@@ -112,7 +112,7 @@ export class IssueTypeService extends TaskStatusPrioritySizeService<IssueType> {
 
 			// Save the created or fetched issue types to the repository and return the result.
-			return await this.typeOrmRepository.save(issueTypes);
+			return await this.saveMany(issueTypes);
 		} catch (error) {
 			throw new BadRequestException(
</file context>
Fix with Cubic

}
}
return await this.typeOrmRepository.save(priorities);
return await this.saveMany(priorities);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: saveMany overwrites tenant/tenantId with RequestContext.currentTenantId, so bulkCreateTenantsTaskPriorities will persist every priority under the current tenant instead of the per-tenant values built in the loop.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/lib/tasks/priorities/priority.service.ts, line 91:

<comment>saveMany overwrites tenant/tenantId with RequestContext.currentTenantId, so bulkCreateTenantsTaskPriorities will persist every priority under the current tenant instead of the per-tenant values built in the loop.</comment>

<file context>
@@ -88,7 +88,7 @@ export class TaskPriorityService extends TaskStatusPrioritySizeService<TaskPrior
 				}
 			}
-			return await this.typeOrmRepository.save(priorities);
+			return await this.saveMany(priorities);
 		} catch (error) {
 			throw new BadRequestException(error);
</file context>
Suggested change
return await this.saveMany(priorities);
return await this.typeOrmRepository.save(priorities);
Fix with Cubic

});
}
await super.delete(id);
return await this.save(entity);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The MikroORM fallback path does not enforce entity.tenantId = tenantId before saving, unlike the TypeORM path above. This asymmetry can allow an entity with a missing or incorrect tenantId to be persisted, breaking tenant isolation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/lib/product-type/product-type.service.ts, line 62:

<comment>The MikroORM fallback path does not enforce `entity.tenantId = tenantId` before saving, unlike the TypeORM path above. This asymmetry can allow an entity with a missing or incorrect `tenantId` to be persisted, breaking tenant isolation.</comment>

<file context>
@@ -37,8 +40,26 @@ export class ProductTypeService extends TenantAwareCrudService<ProductType> {
+				});
+			}
+			await super.delete(id);
+			return await this.save(entity);
 		} catch (err) {
 			throw new BadRequestException(err);
</file context>
Suggested change
return await this.save(entity);
if (isNotEmpty(tenantId)) {
entity.tenantId = tenantId;
}
return await this.save(entity);
Fix with Cubic

// Use base class super.findAll which handles both ORMs every time here because we supply explicit tenant
// scoping via the where clause (tenantId: RequestContext.currentTenantId() || params.tenantId), so we
// intentionally bypass any automatic tenant scoping and rely on our explicit filter.
const result = await super.findAll(options as FindManyOptions<BaseEntity>);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: super.findAll applies tenant scoping and overrides the IsNull() tenant filter in getDefaultEntities, so system defaults (tenantId=null) won’t be returned for authenticated tenants.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/lib/tasks/task-status-priority-size.service.ts, line 117:

<comment>super.findAll applies tenant scoping and overrides the IsNull() tenant filter in getDefaultEntities, so system defaults (tenantId=null) won’t be returned for authenticated tenants.</comment>

<file context>
@@ -112,25 +111,12 @@ export class TaskStatusPrioritySizeService<
+			// Use base class super.findAll which handles both ORMs every time here because we supply explicit tenant
+			// scoping via the where clause (tenantId: RequestContext.currentTenantId() || params.tenantId), so we
+			// intentionally bypass any automatic tenant scoping and rely on our explicit filter.
+			const result = await super.findAll(options as FindManyOptions<BaseEntity>);
+			items = result.items;
+			total = result.total;
</file context>
Fix with Cubic

if (ids.length > 0) {
await super.deleteMany(ids);
}
return productVariantSettings;
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: deleteManySettings always returns the input array instead of the actual delete result, so callers like ProductDeleteHandler will over-count deletions whenever super.deleteMany removes fewer rows than the input size (tenant scoping, missing ids). Return the real DeleteResult/[] or an array that reflects actual deletions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/lib/product-setting/product-setting.service.ts, line 37:

<comment>deleteManySettings always returns the input array instead of the actual delete result, so callers like ProductDeleteHandler will over-count deletions whenever super.deleteMany removes fewer rows than the input size (tenant scoping, missing ids). Return the real DeleteResult/[] or an array that reflects actual deletions.</comment>

<file context>
@@ -14,20 +14,26 @@ export class ProductVariantSettingService extends TenantAwareCrudService<Product
+		if (ids.length > 0) {
+			await super.deleteMany(ids);
+		}
+		return productVariantSettings;
 	}
 }
</file context>
Fix with Cubic

@nx-cloud
Copy link

nx-cloud bot commented Feb 23, 2026

View your CI Pipeline Execution ↗ for commit b921136

Command Status Duration Result
nx build desktop --base-href ./ ✅ Succeeded 1s View ↗
nx build desktop-api --output-path=dist/apps/de... ✅ Succeeded <1s View ↗
nx run api:desktop-api ✅ Succeeded 9s View ↗
nx run gauzy:desktop-ui --base-href ./ ✅ Succeeded 3m 45s View ↗
nx run-many -t build -c production -p constants... ✅ Succeeded 9s View ↗
nx build api -c=production --prod ✅ Succeeded 5s View ↗
nx run-many -t build -c development -p constant... ✅ Succeeded 10s View ↗
nx build gauzy -c=production --prod --verbose ✅ Succeeded 1m 6s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-23 22:31:04 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants