-
Notifications
You must be signed in to change notification settings - Fork 74
feat: ecosystem service and create ecosystem invitation API route #1540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: ecosystem service and create ecosystem invitation API route #1540
Conversation
Signed-off-by: sujitaw <sujit.sutar@ayanworks.com>
Signed-off-by: sujitaw <sujit.sutar@ayanworks.com>
Signed-off-by: sujitaw <sujit.sutar@ayanworks.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 WalkthroughWalkthroughAdds a new Ecosystem feature: API Gateway endpoints and wiring, a standalone Ecosystem microservice (NATS) with DTOs, repository, service, templates, Prisma schema + migrations/seed updates, enums/response messages, and an env var for NATS seed. Changes
Sequence Diagram(s)sequenceDiagram
actor PlatformAdmin as Platform Admin
participant AG as API Gateway
participant EcoSvc as Ecosystem Microservice
participant Repo as Ecosystem Repository
participant DB as Database
participant Email as Email Service
PlatformAdmin->>AG: POST /ecosystem/invitations { email }
AG->>EcoSvc: NATS -> invite-user-for-ecosystem-creation { email, platformAdminId }
EcoSvc->>Repo: createEcosystemInvitation({ email, platformAdminId })
Repo->>DB: INSERT ecosystem_invitations
DB-->>Repo: invitation record
Repo-->>EcoSvc: invitation
EcoSvc->>EcoSvc: checkUserExistInPlatform(email) via NATS
alt user exists
EcoSvc->>Email: sendInviteEmailTemplate(email, true)
else user not exists
EcoSvc->>Email: sendInviteEmailTemplate(email, false)
end
EcoSvc-->>AG: invitation response
AG-->>PlatformAdmin: 201 Created
sequenceDiagram
actor User
participant AG as API Gateway
participant EcoSvc as Ecosystem Microservice
participant Repo as Ecosystem Repository
participant DB as Database
User->>AG: POST /ecosystem/:orgId (CreateEcosystemDto)
AG->>EcoSvc: NATS -> create-ecosystem { createEcosystemDto }
EcoSvc->>Repo: checkEcosystemNameExist(name)
Repo->>DB: SELECT ecosystem WHERE name=?
alt name exists
Repo-->>EcoSvc: existing record
EcoSvc-->>AG: 409 Conflict
AG-->>User: 409 Conflict
else name available
Repo-->>EcoSvc: null
EcoSvc->>Repo: checkEcosystemOrgs(orgId)
Repo->>DB: SELECT ecosystem_orgs WHERE orgId=?
alt org already linked
Repo-->>EcoSvc: existing record
EcoSvc-->>AG: 400 Bad Request
AG-->>User: 400 Bad Request
else proceed
EcoSvc->>Repo: createNewEcosystem(dto)
Repo->>DB: BEGIN TRANSACTION / INSERT ecosystem, ecosystem_users, ecosystem_orgs
DB-->>Repo: created ecosystem
Repo-->>EcoSvc: IEcosystem
EcoSvc-->>AG: IEcosystem
AG-->>User: 201 Created
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 15
🧹 Nitpick comments (19)
nest-cli.json (1)
200-208: Consider alphabetical ordering for project entries.The configuration is correct but is positioned between "organization" and "platform-service". For improved maintainability, consider placing project entries in alphabetical order.
🔎 Suggested placement
Move the ecosystem entry to appear before "geo-location" (line 110) to maintain alphabetical order:
"enum": { "type": "library", "root": "libs/enum", "entryFile": "index", "sourceRoot": "libs/enum/src", "compilerOptions": { "tsConfigPath": "libs/enum/tsconfig.lib.json" } }, + "ecosystem": { + "type": "application", + "root": "apps/ecosystem", + "entryFile": "main", + "sourceRoot": "apps/ecosystem/src", + "compilerOptions": { + "tsConfigPath": "apps/ecosystem/tsconfig.app.json" + } + }, "geo-location": { "type": "application", "root": "apps/geo-location",apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (1)
8-13: Consider removing redundant IsString decorator.The
@IsEmaildecorator already validates that the value is a string, making@IsStringredundant. However, keeping it can improve error message clarity for API consumers.apps/ecosystem/templates/create-ecosystem.templates.ts (1)
32-34: Consider escaping environment variables used in HTML context.While environment variables are typically controlled by administrators, applying
escapeHtmltoPLATFORM_NAMEand other environment variables displayed in HTML would provide defense-in-depth against misconfiguration.🔎 Example hardening
const safeEmail = escapeHtml(email); const safeInviterName = escapeHtml(inviterName); + const safePlatformName = escapeHtml(process.env.PLATFORM_NAME); + const safePoweredBy = escapeHtml(process.env.POWERED_BY);Then use
safePlatformNameandsafePoweredByin the template instead of directprocess.envaccess.libs/prisma-service/prisma/migrations/20251230074431_create_ecosystem_invitation_workflow_table/migration.sql (1)
2-17: Consider adding foreign keys for audit columns.The
createdByandlastChangedBycolumns store UUIDs but lack foreign key constraints to theusertable. While this might be intentional for flexibility, adding foreign keys would enforce referential integrity.🔎 Proposed addition
-- AddForeignKey ALTER TABLE "ecosystem" ADD CONSTRAINT "ecosystem_createdBy_fkey" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "ecosystem" ADD CONSTRAINT "ecosystem_lastChangedBy_fkey" FOREIGN KEY ("lastChangedBy") REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE CASCADE;Apply similar constraints to other tables with audit columns. Note: If system users or deleted users need to be preserved in audit trails, consider using ON DELETE SET NULL instead of RESTRICT.
libs/prisma-service/prisma/schema.prisma (2)
802-817: Consider adding onDelete behavior for ecosystem_invitations relations.The
ecosystemIdanduserIdare optional, which is appropriate for pending invitations. However, consider what should happen when the referencedecosystemoruseris deleted. Without explicitonDeleterules, the database default behavior applies, which may leave orphaned invitations.🔎 Suggested improvement
- ecosystem ecosystem? @relation(fields: [ecosystemId], references: [id]) - user user? @relation(fields: [userId], references: [id]) + ecosystem ecosystem? @relation(fields: [ecosystemId], references: [id], onDelete: SetNull) + user user? @relation(fields: [userId], references: [id], onDelete: SetNull)
781-800: Minor formatting: Remove extra blank line.There's an extra blank line at line 798 before the
@@uniqueconstraint. This is a minor cosmetic issue.🔎 Suggested fix
ecosystem ecosystem @relation(fields: [ecosystemId], references: [id]) ecosystemRole ecosystem_roles @relation(fields: [ecosystemRoleId], references: [id]) organisation organisation @relation(fields: [orgId], references: [id]) - - + @@unique([orgId, ecosystemId]) }.env.sample (1)
121-121: Consider ordering and quoting for consistency.Static analysis flagged two issues:
Key ordering:
ECOSYSTEM_NKEY_SEEDshould be placed beforeISSUANCE_NKEY_SEEDto maintain alphabetical ordering (E before I).Value quoting: While other
NKEY_SEEDvalues in this file also lack quotes, it's generally safer to quote environment variable values to prevent shell interpretation issues.🔎 Suggested fix - reorder and quote
Move the line between
CONNECTION_NKEY_SEEDandCREDENTAILDEFINITION_NKEY_SEED(or beforeISSUANCE_NKEY_SEEDfor alphabetical order):CONNECTION_NKEY_SEED=xxxxxxxxxxxxx // Please provide Nkeys secret for connection service +ECOSYSTEM_NKEY_SEED='xxxxxxxxxxxxx' // Please provide Nkeys secret for ecosystem service CREDENTAILDEFINITION_NKEY_SEED=xxxxxxxxxxxxx // Please provide Nkeys secret for credential-definition service -ECOSYSTEM_NKEY_SEED=xxxxxxxxxxxxx // Please provide Nkeys secret for ecosystem serviceapps/ecosystem/src/main.ts (2)
9-9: Remove commented-out import.The commented import
// import { nkeyAuthenticator } from 'nats';is unused and should be removed to keep the code clean.🔎 Suggested fix
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter'; -// import { nkeyAuthenticator } from 'nats'; import { getNatsOptions } from '@credebl/common/nats.config';
14-25: Consider adding error handling for bootstrap failures.The bootstrap function doesn't catch or handle errors that may occur during startup. If
NestFactory.createMicroserviceorapp.listen()fails, the process will exit without logging the error clearly.🔎 Suggested improvement
async function bootstrap(): Promise<void> { - const app = await NestFactory.createMicroservice<MicroserviceOptions>(EcosystemModule, { - transport: Transport.NATS, - options: getNatsOptions(CommonConstants.ECOSYSTEM_SERVICE, process.env.ECOSYSTEM_NKEY_SEED) - }); - app.useLogger(app.get(NestjsLoggerServiceAdapter)); - app.useGlobalFilters(new HttpExceptionFilter()); - - await app.listen(); - logger.log('Ecosystem Microservice is listening to NATS '); + try { + const app = await NestFactory.createMicroservice<MicroserviceOptions>(EcosystemModule, { + transport: Transport.NATS, + options: getNatsOptions(CommonConstants.ECOSYSTEM_SERVICE, process.env.ECOSYSTEM_NKEY_SEED) + }); + app.useLogger(app.get(NestjsLoggerServiceAdapter)); + app.useGlobalFilters(new HttpExceptionFilter()); + + await app.listen(); + logger.log('Ecosystem Microservice is listening to NATS'); + } catch (error) { + logger.error('Failed to start Ecosystem Microservice', error); + process.exit(1); + } } -bootstrap(); +bootstrap();libs/enum/src/enum.ts (1)
108-110: Consider adding more status values to EcosystemOrgStatus.The enum currently only defines
ACTIVE, but organization status typically includes additional states such asINACTIVE,PENDING,SUSPENDED, etc. If other statuses are not needed in the current implementation, this is acceptable, but consider whether this enum will need expansion in the future.apps/ecosystem/src/ecosystem.controller.ts (1)
23-32: Remove or implement the commented-out code.The commented-out
createEcosystemendpoint should either be implemented if needed or removed to reduce clutter.apps/ecosystem/repositories/ecosystem.repository.ts (1)
32-147: Remove the commented-out code.Large blocks of inactive code reduce maintainability. If this functionality is planned for future use, consider tracking it in an issue instead.
apps/ecosystem/src/ecosystem.service.ts (3)
33-38: Consider transactional consistency between database and email operations.The invitation is created in the database (line 34) before sending the email (line 36). If email sending fails, the invitation record remains in the database with no notification sent to the user. Consider wrapping both operations or implementing a compensating action to delete the invitation if email sending fails.
39-42: Improve error handling specificity.The catch block uses a generic
invalidInvitationStatusmessage for all errors. This may not accurately reflect the actual failure (e.g., database errors, email sending failures, validation errors). Consider using more specific error messages based on the error type.
61-115: Remove the commented-out code.Large blocks of inactive code reduce readability and maintainability. If this functionality is planned, track it in an issue instead.
apps/api-gateway/src/ecosystem/ecosystem.controller.ts (2)
52-67: Consider alternative to mutating the DTO.Line 57 directly mutates
sendEcosystemCreateDto.userIdby assigning the path parameter. While functional, mutating request DTOs can lead to unexpected behavior in middleware or interceptors that operate on the original request body.🔎 Alternative approach
async createInvitation( @Body() sendEcosystemCreateDto: SendEcosystemCreateDto, @Param('userId') userId: string, @Res() res: Response ): Promise<Response> { - sendEcosystemCreateDto.userId = userId; - - await this.ecosystemService.ecosystemCreateInvitation(sendEcosystemCreateDto); + await this.ecosystemService.ecosystemCreateInvitation({ + ...sendEcosystemCreateDto, + userId + }); const finalResponse: IResponse = {
69-100: Remove the commented-out code.The commented-out
createNewEcosystemendpoint should either be implemented if needed or removed to maintain code cleanliness.apps/api-gateway/src/ecosystem/ecosystem.service.ts (1)
23-31: Consider removing commented code or adding a TODO.The commented
createEcosystemmethod appears to be placeholder code for future functionality. Consider either:
- Adding a TODO comment with a tracking ticket reference, or
- Removing it entirely and adding it when the functionality is ready to be implemented.
This helps keep the codebase clean and makes future intentions more explicit.
apps/ecosystem/dtos/create-ecosystem-dto.ts (1)
47-47: Consider adding validation for orgId when provided.The
orgIdfield is optional but has no validation decorators. If this field represents an organization identifier (likely a UUID based on patterns elsewhere in the codebase), consider adding validation when it's provided to ensure data integrity.🔎 Example validation
@ApiPropertyOptional() + @IsOptional() + @IsString({ message: 'orgId must be in string format.' }) + @IsUUID('4', { message: 'orgId must be a valid UUID.' }) orgId?: string;
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
.env.sampleapps/api-gateway/src/app.module.tsapps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.tsapps/api-gateway/src/ecosystem/ecosystem.controller.tsapps/api-gateway/src/ecosystem/ecosystem.module.tsapps/api-gateway/src/ecosystem/ecosystem.service.tsapps/ecosystem/dtos/create-ecosystem-dto.tsapps/ecosystem/interfaces/ecosystem.intefaces.tsapps/ecosystem/repositories/ecosystem.repository.tsapps/ecosystem/src/ecosystem.controller.tsapps/ecosystem/src/ecosystem.module.tsapps/ecosystem/src/ecosystem.service.tsapps/ecosystem/src/main.tsapps/ecosystem/templates/create-ecosystem.templates.tsapps/ecosystem/tsconfig.app.jsonlibs/common/src/common.constant.tslibs/common/src/response-messages/index.tslibs/enum/src/enum.tslibs/prisma-service/prisma/migrations/20251230074431_create_ecosystem_invitation_workflow_table/migration.sqllibs/prisma-service/prisma/schema.prismanest-cli.json
🧰 Additional context used
🧬 Code graph analysis (7)
apps/api-gateway/src/ecosystem/ecosystem.module.ts (14)
apps/api-gateway/src/app.module.ts (1)
Module(40-123)apps/ecosystem/src/ecosystem.module.ts (1)
Module(18-37)apps/api-gateway/src/issuance/issuance.module.ts (1)
Module(12-26)apps/api-gateway/src/authz/authz.module.ts (1)
Module(26-63)apps/api-gateway/src/organization/organization.module.ts (1)
Module(13-29)apps/api-gateway/src/verification/verification.module.ts (1)
Module(11-25)apps/api-gateway/src/agent-service/agent-service.module.ts (1)
Module(13-30)apps/api-gateway/src/credential-definition/credential-definition.module.ts (1)
Module(10-28)apps/api-gateway/src/connection/connection.module.ts (1)
Module(9-25)apps/api-gateway/src/fido/fido.module.ts (1)
Module(9-23)apps/api-gateway/src/platform/platform.module.ts (1)
Module(9-23)apps/api-gateway/src/schema/schema.module.ts (1)
Module(11-26)apps/api-gateway/src/user/user.module.ts (1)
Module(13-29)libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (1)
libs/common/src/cast.helper.ts (1)
trim(39-43)
apps/ecosystem/repositories/ecosystem.repository.ts (2)
apps/ecosystem/src/ecosystem.service.ts (1)
Injectable(13-59)libs/common/src/interfaces/cloud-wallet.interface.ts (1)
Invitation(268-275)
apps/ecosystem/dtos/create-ecosystem-dto.ts (3)
libs/common/src/cast.helper.ts (2)
trim(39-43)IsNotSQLInjection(96-127)libs/validations/minLength.ts (1)
MinLength(3-28)libs/validations/maxLength.ts (1)
MaxLength(3-28)
apps/ecosystem/interfaces/ecosystem.intefaces.ts (1)
apps/api-gateway/src/issuance/utils/helper.ts (1)
JsonValue(5-5)
apps/ecosystem/src/ecosystem.controller.ts (1)
apps/ecosystem/interfaces/ecosystem.intefaces.ts (1)
IEcosystemInvitations(65-73)
apps/ecosystem/templates/create-ecosystem.templates.ts (1)
libs/common/src/common.utils.ts (1)
escapeHtml(149-156)
🪛 dotenv-linter (4.0.0)
.env.sample
[warning] 121-121: [UnorderedKey] The ECOSYSTEM_NKEY_SEED key should go before the ISSUANCE_NKEY_SEED key
(UnorderedKey)
[warning] 121-121: [ValueWithoutQuotes] This value needs to be surrounded in quotes
(ValueWithoutQuotes)
🔇 Additional comments (13)
apps/ecosystem/tsconfig.app.json (1)
1-9: LGTM!The TypeScript configuration correctly extends the root configuration and follows standard NestJS monorepo conventions.
apps/ecosystem/templates/create-ecosystem.templates.ts (1)
17-18: LGTM!Proper use of
escapeHtmlto prevent XSS attacks via user-provided email and inviter name.libs/prisma-service/prisma/migrations/20251230074431_create_ecosystem_invitation_workflow_table/migration.sql (2)
86-105: LGTM!Foreign key constraints are properly defined with appropriate ON DELETE and ON UPDATE actions. The use of RESTRICT for critical relationships and SET NULL for invitations provides good data integrity.
77-84: LGTM!Unique indexes effectively prevent duplicate role names and duplicate user/organization associations within ecosystems.
libs/prisma-service/prisma/schema.prisma (2)
735-752: LGTM! Well-structured ecosystem model.The ecosystem model is properly defined with UUID primary key, timestamps, and soft delete support. The
autoEndorsementboolean with defaultfalseis a good safety default.One consideration: The
ledgersfield is defined asJson?. If this will store references to ledger entities, consider whether a proper relation to theledgersmodel would provide better type safety and referential integrity.
39-40: LGTM! Properly added ecosystem relations to existing models.The relations
ecosystemUsers,ecosystemInvitationsonuser, andecosystemOrgsonorganisationare correctly defined to support the new ecosystem feature.Also applies to: 160-160
libs/common/src/common.constant.ts (1)
257-259: LGTM! Properly added ecosystem service constant.The
ECOSYSTEM_SERVICE = 'ecosystem'constant is correctly added and follows the existing naming conventions. The placement under a clear// ecosystemcomment section is appropriate.apps/api-gateway/src/ecosystem/ecosystem.module.ts (1)
10-23: LGTM! Module follows established patterns.The
EcosystemModulecorrectly follows the established pattern used by other API gateway modules (FidoModule, SchemaModule, PlatformModule, etc.):
- Registers NATS client with appropriate service name and gateway seed
- Declares controller and service providers
- Uses
NATSClientfor inter-service communicationapps/api-gateway/src/app.module.ts (2)
68-68: LGTM! EcosystemModule properly integrated.The
EcosystemModuleis correctly imported and added to the API gateway's module imports. The placement follows the alphabetical ordering pattern used by other modules.
87-122: Verify if any ecosystem routes should be excluded from AuthzMiddleware.The
EcosystemModuleis added but no ecosystem routes are excluded fromAuthzMiddleware. This means all ecosystem endpoints will require authorization, which is likely the correct behavior for ecosystem management operations.If any ecosystem endpoints should be publicly accessible (e.g., invitation acceptance), they may need to be added to the exclusion list.
apps/ecosystem/src/ecosystem.module.ts (1)
18-37: [Your rewritten review comment text here]
[Exactly ONE classification tag]libs/common/src/response-messages/index.ts (1)
163-250: LGTM! Well-structured response messages.The ecosystem response messages section is well-organized and consistent with the existing patterns in the codebase. The messages are clear, descriptive, and cover a comprehensive range of success and error scenarios for ecosystem operations.
apps/ecosystem/dtos/create-ecosystem-dto.ts (1)
33-33: No action required — userId is correctly set programmatically by the controller.The
userIdfield is assigned by the controller from the URL path parameter (@Post('/:userId/invitations')→@Param('userId')) and then set directly on the DTO before validation (sendEcosystemCreateDto.userId = userId;). Since it is not populated from user input, it does not require input validation decorators like other user-provided string fields.
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts
Outdated
Show resolved
Hide resolved
| async ecosystemCreateInvitation(invitationDto: SendEcosystemCreateDto): Promise<IEcosystemInvitations> { | ||
| const { email, userId } = invitationDto; | ||
|
|
||
| try { | ||
| const invitation = await this.ecosystemRepository.createSendInvitation(email, userId); | ||
|
|
||
| await this.sendInviteEmailTemplate(email); | ||
|
|
||
| return invitation; | ||
| } catch (error) { | ||
| this.logger.error(`ecosystemCreateInvitation error: ${JSON.stringify(error)}`); | ||
| throw new InternalServerErrorException(ResponseMessages.user.error.invalidInvitationStatus); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add ecosystemId parameter to invitation creation.
The repository's createSendInvitation method is called without an ecosystemId, but the IEcosystemInvitations interface requires this field. This aligns with the issue identified in the repository file.
🔎 Proposed fix
- async ecosystemCreateInvitation(invitationDto: SendEcosystemCreateDto): Promise<IEcosystemInvitations> {
- const { email, userId } = invitationDto;
+ async ecosystemCreateInvitation(invitationDto: SendEcosystemCreateDto): Promise<IEcosystemInvitations> {
+ const { email, userId, ecosystemId } = invitationDto;
try {
- const invitation = await this.ecosystemRepository.createSendInvitation(email, userId);
+ const invitation = await this.ecosystemRepository.createSendInvitation(email, userId, ecosystemId);
await this.sendInviteEmailTemplate(email);
return invitation;This requires that SendEcosystemCreateDto includes an ecosystemId field.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async ecosystemCreateInvitation(invitationDto: SendEcosystemCreateDto): Promise<IEcosystemInvitations> { | |
| const { email, userId } = invitationDto; | |
| try { | |
| const invitation = await this.ecosystemRepository.createSendInvitation(email, userId); | |
| await this.sendInviteEmailTemplate(email); | |
| return invitation; | |
| } catch (error) { | |
| this.logger.error(`ecosystemCreateInvitation error: ${JSON.stringify(error)}`); | |
| throw new InternalServerErrorException(ResponseMessages.user.error.invalidInvitationStatus); | |
| } | |
| } | |
| async ecosystemCreateInvitation(invitationDto: SendEcosystemCreateDto): Promise<IEcosystemInvitations> { | |
| const { email, userId, ecosystemId } = invitationDto; | |
| try { | |
| const invitation = await this.ecosystemRepository.createSendInvitation(email, userId, ecosystemId); | |
| await this.sendInviteEmailTemplate(email); | |
| return invitation; | |
| } catch (error) { | |
| this.logger.error(`ecosystemCreateInvitation error: ${JSON.stringify(error)}`); | |
| throw new InternalServerErrorException(ResponseMessages.user.error.invalidInvitationStatus); | |
| } | |
| } |
🤖 Prompt for AI Agents
In apps/ecosystem/src/ecosystem.service.ts around lines 30 to 43, the call to
createSendInvitation omits the required ecosystemId causing the returned
IEcosystemInvitations to miss that field; extract ecosystemId from
SendEcosystemCreateDto (const { email, userId, ecosystemId } = invitationDto),
pass ecosystemId into this.ecosystemRepository.createSendInvitation(email,
userId, ecosystemId), and ensure SendEcosystemCreateDto (and any callers) are
updated to include ecosystemId so the repository receives and persists it.
744505a to
00d219b
Compare
Signed-off-by: sujitaw <sujit.sutar@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
…ation api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
392d634 to
99daedc
Compare
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
|
@coderabbitai full-review |
|
@pranalidhanavade, I'll perform a comprehensive review of all the changes in this PR. Let me analyze the ecosystem service implementation, API routes, database schema changes, and overall architecture. ✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
libs/prisma-service/prisma/seed.ts (2)
243-254: Critical: Inverted condition causes incorrect behavior.The condition
if (!userId && !orgId && !orgRoleId)will only enter the block when ALL values are null/undefined, but then immediately tries to access.idon null objects (lines 246-248), causing a runtime error. The logic should check if all values ARE defined before proceeding.🐛 Proposed fix
- if (!userId && !orgId && !orgRoleId) { + if (userId && orgId && orgRoleId) { const platformOrganization = await prisma.user_org_roles.create({ data: { userId: userId.id, orgRoleId: orgRoleId.id, orgId: orgId.id } }); logger.log(platformOrganization); } else { - logger.log('Already seeding in org_roles'); + logger.log('Required entities not found for user_org_roles seeding'); }
496-499: Security concern: Passing encrypted secrets via command line arguments.Command line arguments can be visible in process listings (
ps aux) and shell history. Consider using environment variables or piping the secrets via stdin instead.
🤖 Fix all issues with AI agents
In @apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts:
- Line 14: The userId field in the SendEcosystemInvitation DTO lacks validation;
update the DTO by adding class-validator decorators to ensure userId is a
required, non-empty string (e.g., annotate the userId property with @IsString()
and @IsNotEmpty(), or @IsUUID() if the app expects UUIDs) so incoming payloads
are validated before use.
In @apps/api-gateway/src/ecosystem/ecosystem.controller.ts:
- Around line 46-70: The @Roles(OrgRoles.PLATFORM_ADMIN) decorator on
createInvitation is not effective because OrgRolesGuard is not applied; update
the controller method to include the OrgRolesGuard so role checks run (e.g., add
UseGuards(AuthGuard('jwt'), OrgRolesGuard) or combine into a single decorator
that applies both guards), ensuring the OrgRolesGuard symbol is imported and
used alongside AuthGuard for the createInvitation route.
- Around line 119-127: The createNewEcosystem handler types the user param as
plain object which loses type safety; change the parameter type to the Prisma
user type used elsewhere (e.g., User from @prisma/client) and update the import
accordingly, then use dot-access (user?.id) rather than bracket notation when
assigning createEcosystemDto.userId; ensure the function signature for
createNewEcosystem and any other endpoints in this controller use the same
Prisma User type for consistency.
In @apps/api-gateway/src/ecosystem/ecosystem.module.ts:
- Around line 10-23: The getNatsOptions call in EcosystemModule uses the wrong
env var: replace process.env.API_GATEWAY_NKEY_SEED with
process.env.ECOSYSTEM_NKEY_SEED so the NATS options use the ecosystem seed like
main.ts does; update the ClientsModule.register entry (the object with name
'NATS_CLIENT' and transport Transport.NATS) to pass
process.env.ECOSYSTEM_NKEY_SEED into
getNatsOptions(CommonConstants.ECOSYSTEM_SERVICE, ...), leaving getNatsOptions,
CommonConstants.ECOSYSTEM_SERVICE, EcosystemService, EcosystemController and
NATSClient unchanged.
In @apps/ecosystem/dtos/create-ecosystem-dto.ts:
- Line 40: The orgId property in CreateEcosystemDto is optional but missing
validation decorators; update the orgId field in the CreateEcosystemDto class by
adding @IsOptional() and @IsUUID() from class-validator (and add those imports
if missing) so the DTO consistently enforces an optional UUID value for orgId.
- Line 32: The userId property in the CreateEcosystemDto lacks validation;
update the DTO by adding class-validator decorators such as @IsUUID() and
@IsNotEmpty() (and optionally @IsString()) to the userId property and add IsUUID
(and IsNotEmpty) to the existing imports from class-validator so the
CreateEcosystemDto.userId is validated as a required UUID.
In @apps/ecosystem/repositories/ecosystem.repository.ts:
- Around line 245-250: Replace the hardcoded membersCount and endorsementsCount
with real computed values (e.g., derive membersCount from ecosystem.members
length or the appropriate relation and endorsementsCount from
ecosystem.endorsements or the correct field) and guard access to
ecosystem.ecosystemOrgs[0] when building ecosystemLead by using optional
chaining/defaults so role and orgName are null or empty string if the array is
empty; reference the same symbols (membersCount, endorsementsCount,
ecosystem.ecosystemOrgs, ecosystemLead, ecosystemRole, organisation) when making
these changes so the code reads actual counts and safely handles missing
ecosystemOrgs.
- Around line 97-113: The code calls this.prisma.ecosystem_roles.findFirst
inside the transaction, which executes outside the transaction and can return
null; instead use the transaction-scoped prisma (the local prisma variable
passed into the $transaction callback) to query ecosystem_roles (e.g.,
prisma.ecosystem_roles.findFirst) and then check the result for null before
using ecosystemRoleDetails.id — if null, throw or handle an explicit error so
the transaction will rollback and avoid a null pointer when creating the
ecosystem_orgs record that references ecosystemRoleDetails.id.
In @apps/ecosystem/src/ecosystem.controller.ts:
- Around line 43-46: The createEcosystem @MessagePattern handler incorrectly
uses the HTTP-only @Body() decorator; remove @Body() from the createEcosystem
method signature so the handler accepts the message payload as the first
parameter directly (e.g., rename the parameter to payload: { createEcosystemDto
} or typed payload) and pass payload.createEcosystemDto to
ecosystemService.createEcosystem; update the method signature in the
createEcosystem function accordingly so it reflects a microservice
MessagePattern handler.
In @apps/ecosystem/src/ecosystem.module.ts:
- Around line 18-37: The module currently lets ClientsModule.register call
getNatsOptions with process.env.ECOSYSTEM_NKEY_SEED which can be undefined,
causing an unauthenticated NATS connection; update EcosystemModule to validate
ECOSYSTEM_NKEY_SEED at startup and fail fast: in the module
bootstrap/constructor (or before calling ClientsModule.register) check
process.env.ECOSYSTEM_NKEY_SEED (or use a ConfigService) and throw a clear error
if missing, or alternatively change the ClientsModule.register call for
NATS_CLIENT to only register when the env var exists and otherwise skip
registration while logging a clear message; reference getNatsOptions,
ECOSYSTEM_NKEY_SEED, ClientsModule.register, NATS_CLIENT and EcosystemModule
when making the change.
In @apps/ecosystem/src/ecosystem.service.ts:
- Around line 67-79: The code in sendInviteEmailTemplate calls
this.prisma.platform_config.findFirst() which can return null, then immediately
uses platformConfigData.emailFrom causing a potential runtime null dereference;
update sendInviteEmailTemplate to handle a missing platformConfigData by
checking if platformConfigData is null (or use a safe default) before reading
platformConfigData.emailFrom, e.g., compute a fallback sender value and assign
emailData.emailFrom from platformConfigData.emailFrom ?? fallback, and ensure
emailData is populated before calling this.emailService.sendEmail so
sendInviteEmailTemplate never accesses properties on a null platformConfigData.
In @libs/common/src/response-messages/index.ts:
- Line 205: Fix the typo in the response message for
signTransactionNotApplicable by changing the misspelled word "aapllicable" to
"applicable" in the signTransactionNotApplicable entry so the string reads
"Signing transaction for w3c schema is not applicable".
- Line 215: The message string for the response key credentialDefinitionNotFound
is incorrect; update the value associated with credentialDefinitionNotFound in
the response-messages export to "Credential definition not found" so the text
matches the error key name and intent (ensure you modify the entry named
credentialDefinitionNotFound in libs/common/src/response-messages/index.ts).
In
@libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json:
- Around line 178-188: In the ecosystemRoleData array, remove the trailing
whitespace character after the "description": "Ecosystem Lead" value (the object
whose "name" is "Ecosystem Lead") so the string ends exactly with "Ecosystem
Lead" without extra spaces; update that JSON entry to eliminate the stray
whitespace for consistency.
In
@libs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql:
- Around line 62-74: The migration for CREATE TABLE "ecosystem_invitations" is
missing the optional ecosystemId column referenced by the interface; add a
nullable "ecosystemId" UUID column to the "ecosystem_invitations" table and
create a foreign key constraint referencing "ecosystem"("id") (e.g., CONSTRAINT
"ecosystem_invitations_ecosystemId_fkey" FOREIGN KEY ("ecosystemId") REFERENCES
"ecosystem"("id")), and optionally add an index on "ecosystemId" for lookups.
In @libs/prisma-service/prisma/schema.prisma:
- Around line 801-814: The Prisma model ecosystem_invitations is missing the
ecosystemId column that IEcosystemInvitations expects; add an optional
ecosystemId String? @db.Uuid field to the ecosystem_invitations model, create
the relation decorator (e.g., ecosystem ecosystem? @relation(fields:
[ecosystemId], references: [id])) and update the ecosystem model to include the
back-relation (e.g., invitations ecosystem_invitations[]). Alternatively, if
ecosystemId is not needed, remove it from the IEcosystemInvitations interface to
keep the schema and interface in sync.
In @libs/prisma-service/prisma/seed.ts:
- Around line 541-545: The loop in updateClientId accesses
cachedConfig.platformEmail but cachedConfig may be null because
getPlatformConfig() is called later in main(); fix by ensuring cachedConfig is
initialized before updateClientId runs (move the getPlatformConfig() call in
main() to occur before updateClientId()), or alternatively add a defensive null
check in updateClientId (guard on cachedConfig and skip the platform admin check
if cachedConfig is null) so cachedConfig.platformEmail is never dereferenced
when null.
🧹 Nitpick comments (17)
apps/ecosystem/src/main.ts (1)
9-9: Remove commented-out import.The commented import
// import { nkeyAuthenticator } from 'nats';is unused and should be removed to keep the code clean.🧹 Proposed fix
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter'; -// import { nkeyAuthenticator } from 'nats'; import { getNatsOptions } from '@credebl/common/nats.config';apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (2)
6-15: Clarify the naming inconsistency between class name and purpose.The class is named
SendEcosystemCreateDto(suggesting ecosystem creation) but the file is namedsend-ecosystem-invitation.ts(suggesting invitation sending). Consider renaming the class toSendEcosystemInvitationDtofor consistency with the file name and apparent purpose.♻️ Rename for consistency
-export class SendEcosystemCreateDto { +export class SendEcosystemInvitationDto { @ApiProperty({ example: 'awqx@yopmail.com' }) @IsEmail({}, { message: 'Please provide a valid email' }) @IsNotEmpty({ message: 'Email is required' }) @IsString({ message: 'Email should be a string' }) @Transform(({ value }) => value?.trim()) email: string; userId: string; }
7-7: Consider using an allowed domain for the API example.The example email uses
yopmail.com, which is listed in theDISALLOWED_EMAIL_DOMAINarray incommon.constant.ts(line 898). While this might be intentional for testing purposes, it could be confusing in API documentation.📝 Update example email
- @ApiProperty({ example: 'awqx@yopmail.com' }) + @ApiProperty({ example: 'user@example.com' }) @IsEmail({}, { message: 'Please provide a valid email' })libs/enum/src/enum.ts (1)
108-110: Consider adding additional status values forEcosystemOrgStatus.The enum only defines
ACTIVE, but typical organization lifecycle workflows often require states likePENDING,INACTIVE, orSUSPENDED. Given the invitation flow being introduced, aPENDINGstate may be needed when an organization is invited but hasn't yet fully joined.♻️ Suggested enhancement
export enum EcosystemOrgStatus { - ACTIVE = 'ACTIVE' + ACTIVE = 'ACTIVE', + PENDING = 'PENDING', + INACTIVE = 'INACTIVE' }libs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql (1)
2-17: Consider adding a unique constraint onecosystem.name.The
ecosystemtable allows duplicate names. If ecosystem names should be unique across the platform, add a unique index. The repository methodcheckEcosystemNameExistsuggests name uniqueness is expected.♻️ Suggested addition
+-- CreateIndex +CREATE UNIQUE INDEX "ecosystem_name_key" ON "ecosystem"("name");apps/ecosystem/templates/create-ecosystem.templates.ts (1)
40-41: Add fallback fonts for better email client compatibility.The template uses
font-family: Montserratwithout a fallback stack. Montserrat is a web font that may not be available in all email clients. Add generic fallback fonts.♻️ Suggested fix
- <div style="font-family: Montserrat; font-style: normal; font-weight: 500; + <div style="font-family: Montserrat, Arial, Helvetica, sans-serif; font-style: normal; font-weight: 500;apps/ecosystem/src/ecosystem.controller.ts (2)
43-46: Add explicit type forcreateEcosystemDtoin payload.The payload type uses shorthand property syntax
{ createEcosystemDto }without an explicit type, making the expected structure unclear. Consider using an interface or inline type for better type safety.♻️ Suggested fix
+import { CreateEcosystemDto } from '../dtos/create-ecosystem-dto'; ... @MessagePattern({ cmd: 'create-ecosystem' }) - async createEcosystem(@Body() payload: { createEcosystemDto }): Promise<IEcosystem> { + async createEcosystem(payload: { createEcosystemDto: CreateEcosystemDto }): Promise<IEcosystem> { return this.ecosystemService.createEcosystem(payload.createEcosystemDto); }
10-10: Unusedloggerinstance.The
loggeris instantiated but never used in this controller. Either utilize it for logging or remove it to avoid dead code.♻️ Suggested: either remove or use the logger
export class EcosystemController { constructor(private readonly ecosystemService: EcosystemService) {} - private readonly logger = new Logger('EcosystemController');apps/ecosystem/repositories/ecosystem.repository.ts (2)
117-122: Avoid mutating the transaction result object.Using
deleteto remove properties from the returnedtransactionobject mutates the original Prisma model instance. This is a side effect that can cause unexpected behavior. Instead, create a new object with only the desired fields.♻️ Suggested fix
- // To return selective object data - delete transaction.lastChangedDateTime; - delete transaction.lastChangedBy; - delete transaction.deletedAt; - - return transaction; + // Return selective object data + const { lastChangedDateTime, lastChangedBy, deletedAt, ...sanitizedEcosystem } = transaction; + return sanitizedEcosystem as ecosystem;
37-51: Invitation status is hardcoded toACCEPTED.The comment on Line 40 indicates this should be
PENDINGwhen the accept/reject flow is ready. Ensure this TODO is tracked and addressed before the feature is fully released, as invitations immediately marked asACCEPTEDbypass the approval workflow.Would you like me to open an issue to track implementing the pending invitation workflow?
apps/api-gateway/src/ecosystem/ecosystem.service.ts (1)
20-28: Consider extracting NATS topic strings to constants.The message pattern
'invite-user-for-ecosystem-creation'and similar patterns across methods are hardcoded strings. Extracting these to a shared constants file would improve maintainability and reduce the risk of typos causing silent failures.♻️ Suggested refactor
// In a shared constants file (e.g., libs/common/src/ecosystem.constants.ts) export const EcosystemMessagePatterns = { INVITE_USER_FOR_ECOSYSTEM_CREATION: 'invite-user-for-ecosystem-creation', GET_ECOSYSTEM_INVITATIONS_BY_USER: 'get-ecosystem-invitations-by-user', CREATE_ECOSYSTEM: 'create-ecosystem', GET_ALL_ECOSYSTEMS: 'get-all-ecosystems', GET_ECOSYSTEM_DASHBOARD: 'get-ecosystem-dashboard' } as const;libs/prisma-service/prisma/seed.ts (1)
635-646: Add timeout to Keycloak fetch calls to prevent hanging.The
fetchcalls to Keycloak have no timeout configured. If Keycloak is unresponsive, this will block the seed process indefinitely.♻️ Suggested fix using AbortController
+ const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 30000); + const res = await fetch( `${process.env.KEYCLOAK_DOMAIN}realms/${process.env.KEYCLOAK_REALM}/protocol/openid-connect/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'client_credentials', client_id: PLATFORM_ADMIN_KEYCLOAK_ID, client_secret: PLATFORM_ADMIN_KEYCLOAK_SECRET - }) + }), + signal: controller.signal } ); + clearTimeout(timeout);apps/api-gateway/src/ecosystem/ecosystem.controller.ts (1)
172-204: Inconsistent indentation on@Getdecorator.The
@Getdecorator at line 172 has extra leading whitespace compared to other route decorators. This is a minor formatting issue.♻️ Fix indentation
- @Get('/:ecosystemId/:orgId/dashboard') + @Get('/:ecosystemId/:orgId/dashboard')apps/ecosystem/src/ecosystem.service.ts (2)
81-102: Potentially unused method:checkUserExistInPlatform.This method checks user existence via NATS messaging, but
inviteUserToCreateEcosystem(lines 50-60) determines user existence directly via Prisma query. Consider removing this method if unused, or refactoring to use it consistently.#!/bin/bash # Description: Check if checkUserExistInPlatform is called anywhere rg -n "checkUserExistInPlatform" --type ts
126-132: Inconsistent exception type for database errors.When
getInvitationsByUserIdfails, it throwsInternalServerErrorExceptionwithinvitationNotFoundmessage, but the actual error could be a database connection issue, not a "not found" scenario. Consider using a more appropriate error message or preserving the original error context.♻️ Suggested improvement
try { return await this.ecosystemRepository.getInvitationsByUserId(userId); } catch (error) { this.logger.error('getInvitationsByUserId error', error); - throw new InternalServerErrorException(ResponseMessages.ecosystem.error.invitationNotFound); + throw new InternalServerErrorException(ResponseMessages.ecosystem.error.fetch); }apps/ecosystem/interfaces/ecosystem.interfaces.ts (2)
41-61: Duplicate interface definitions exist across the codebase.
OrgAgentandLedgerDetailsare defined in multiple locations (apps/connection/src/interfaces, apps/issuance/interfaces, apps/ledger/src/interfaces). Consider consolidating these into a shared location likelibs/common/src/interfacesto maintain a single source of truth.#!/bin/bash # Description: Find all OrgAgent interface definitions rg -n "export interface OrgAgent" --type ts
3-16: Clarify the difference betweenlogoUrlandlogofields.
ICreateEcosystemhas bothlogoUrl(line 7) andlogo(line 9) as optional fields. The distinction is unclear - consider documenting the purpose of each or consolidating if they serve the same purpose.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (23)
.env.sampleapps/api-gateway/src/app.module.tsapps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.tsapps/api-gateway/src/ecosystem/ecosystem.controller.tsapps/api-gateway/src/ecosystem/ecosystem.module.tsapps/api-gateway/src/ecosystem/ecosystem.service.tsapps/ecosystem/dtos/create-ecosystem-dto.tsapps/ecosystem/interfaces/ecosystem.interfaces.tsapps/ecosystem/repositories/ecosystem.repository.tsapps/ecosystem/src/ecosystem.controller.tsapps/ecosystem/src/ecosystem.module.tsapps/ecosystem/src/ecosystem.service.tsapps/ecosystem/src/main.tsapps/ecosystem/templates/create-ecosystem.templates.tsapps/ecosystem/tsconfig.app.jsonlibs/common/src/common.constant.tslibs/common/src/response-messages/index.tslibs/enum/src/enum.tslibs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.jsonlibs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sqllibs/prisma-service/prisma/schema.prismalibs/prisma-service/prisma/seed.tsnest-cli.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-17T08:03:16.180Z
Learnt from: KambleSahil3
Repo: credebl/platform PR: 1518
File: libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json:11-20
Timestamp: 2025-11-17T08:03:16.180Z
Learning: In the credebl/platform repository, seed data files like libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json intentionally contain empty strings for sensitive fields (email, username, passwords, API keys, etc.) because these values are populated from .env file at runtime, not hardcoded in the JSON.
Applied to files:
libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.jsonlibs/prisma-service/prisma/seed.ts
🧬 Code graph analysis (9)
apps/api-gateway/src/ecosystem/ecosystem.module.ts (4)
apps/api-gateway/src/app.module.ts (1)
Module(40-123)apps/ecosystem/src/ecosystem.module.ts (1)
Module(18-37)apps/api-gateway/src/schema/schema.module.ts (1)
Module(11-26)libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)
apps/ecosystem/src/main.ts (3)
libs/logger/src/logger.interface.ts (1)
Logger(6-20)libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)libs/logger/src/nestjsLoggerServiceAdapter.ts (1)
NestjsLoggerServiceAdapter(7-41)
apps/api-gateway/src/ecosystem/ecosystem.controller.ts (2)
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (1)
SendEcosystemCreateDto(6-15)libs/common/src/interfaces/response.interface.ts (1)
IResponse(8-13)
apps/ecosystem/dtos/create-ecosystem-dto.ts (3)
libs/common/src/cast.helper.ts (2)
trim(39-43)IsNotSQLInjection(96-127)libs/validations/minLength.ts (1)
MinLength(3-28)libs/validations/maxLength.ts (1)
MaxLength(3-28)
apps/api-gateway/src/ecosystem/ecosystem.service.ts (2)
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (1)
SendEcosystemCreateDto(6-15)apps/ecosystem/interfaces/ecosystem.interfaces.ts (3)
IEcosystemInvitations(63-71)IEcosystem(18-26)IEcosystemDashboard(87-95)
apps/ecosystem/src/ecosystem.service.ts (4)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (4)
IEcosystemInvitations(63-71)ICreateEcosystem(3-16)IEcosystem(18-26)IEcosystemDashboard(87-95)apps/ecosystem/templates/create-ecosystem.templates.ts (1)
CreateEcosystemInviteTemplate(2-84)libs/common/src/dtos/email.dto.ts (1)
EmailDto(1-8)libs/common/src/response-messages/index.ts (1)
ResponseMessages(1-727)
apps/ecosystem/repositories/ecosystem.repository.ts (2)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (2)
ICreateEcosystem(3-16)IEcosystemDashboard(87-95)libs/common/src/response-messages/index.ts (1)
ResponseMessages(1-727)
apps/ecosystem/src/ecosystem.controller.ts (1)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (3)
IEcosystemInvitations(63-71)IEcosystem(18-26)IEcosystemDashboard(87-95)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (4)
apps/api-gateway/src/issuance/utils/helper.ts (1)
JsonValue(5-5)apps/connection/src/interfaces/connection.interfaces.ts (1)
OrgAgent(111-126)apps/issuance/interfaces/issuance.interfaces.ts (1)
OrgAgent(269-284)apps/ledger/src/interfaces/ledgers.interface.ts (1)
LedgerDetails(1-6)
🪛 dotenv-linter (4.0.0)
.env.sample
[warning] 121-121: [UnorderedKey] The ECOSYSTEM_NKEY_SEED key should go before the ISSUANCE_NKEY_SEED key
(UnorderedKey)
[warning] 121-121: [ValueWithoutQuotes] This value needs to be surrounded in quotes
(ValueWithoutQuotes)
🔇 Additional comments (19)
apps/ecosystem/tsconfig.app.json (1)
1-9: LGTM! TypeScript configuration is properly set up.The configuration correctly extends the base TypeScript config, sets appropriate compiler options, and includes/excludes the right paths for a NestJS microservice.
nest-cli.json (1)
200-208: LGTM! Ecosystem project configuration is properly added.The ecosystem project configuration follows the same structure and conventions as other microservices in the monorepo. All required fields are correctly set.
.env.sample (1)
121-121: LGTM! Environment variable properly added.The
ECOSYSTEM_NKEY_SEEDvariable is correctly placed and follows the same naming convention and format as other NKEY_SEED variables in the file. The static analysis warnings about ordering and quotes are false positives—the current format is consistent with the existing pattern.apps/ecosystem/src/main.ts (1)
14-24: LGTM! Microservice bootstrap is properly configured.The bootstrap function correctly:
- Creates a NATS-based microservice with the EcosystemModule
- Configures NATS options using the ECOSYSTEM_NKEY_SEED environment variable
- Applies the logger adapter and global exception filter
- Starts listening with appropriate logging
The implementation follows the same pattern as other microservices in the monorepo.
libs/common/src/common.constant.ts (1)
257-259: LGTM! Ecosystem service constant added correctly.The new
ECOSYSTEM_SERVICEconstant follows the established naming convention and is properly placed within the enum. This will be used for NATS queue configuration in the ecosystem microservice.apps/api-gateway/src/app.module.ts (1)
17-17: LGTM! EcosystemModule integrated correctly.The module is imported and registered following the established pattern used by other feature modules in the API gateway.
Also applies to: 68-68
libs/enum/src/enum.ts (1)
94-98: LGTM!The
EcosystemRolesenum is well-defined with clear semantic values that align with the ecosystem feature's role hierarchy.apps/ecosystem/templates/create-ecosystem.templates.ts (1)
2-14: LGTM!The environment variable validation at startup is a good defensive practice that fails fast with a clear error message listing all missing variables.
apps/ecosystem/dtos/create-ecosystem-dto.ts (1)
8-15: LGTM!The
namefield has comprehensive validation with trimming, length constraints, and SQL injection protection.libs/prisma-service/prisma/schema.prisma (1)
735-751: LGTM!The
ecosystemmodel is well-structured with proper relations to organizations and users, audit fields, and flexible JSON storage for ledgers configuration.libs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql (1)
62-74: Unique constraint onThe
ecosystem_invitationstable has a unique constraint on(email, status)or removed entirely in favor of application-level logic.🔧 Suggested fix
-- CreateIndex -CREATE UNIQUE INDEX "ecosystem_invitations_email_key" ON "ecosystem_invitations"("email"); +-- Consider removing or adjusting this constraint based on business requirements +-- CREATE UNIQUE INDEX "ecosystem_invitations_email_status_key" ON "ecosystem_invitations"("email", "status");Likely an incorrect or invalid review comment.
apps/api-gateway/src/ecosystem/ecosystem.service.ts (2)
1-13: LGTM! Service setup follows NestJS patterns correctly.The service is properly injectable with appropriate dependency injection for NATS-based inter-service communication.
43-46: Payload structure is correct and aligns with the microservice handler.The
createEcosystemmethod correctly sends payload as{ createEcosystemDto }, which matches the expected signature in the ecosystem microservice controller (line 44:payload: { createEcosystemDto }). While the structure differs from other methods in this service that pass properties directly, this is intentional and required for this specific handler. No changes needed.libs/prisma-service/prisma/seed.ts (2)
139-165: LGTM! Ecosystem roles seeding follows established patterns.The
createEcosystemRolesfunction correctly follows the existing seed pattern: check if data exists, create if not, log appropriately, and handle errors.
812-817: Verify execution order dependencies between seed functions.The new seed functions have interdependencies:
updateClientIdandupdatePlatformUserRoleboth depend oncachedConfigbeing populated bygetPlatformConfig. Ensure the order is correct (as noted in earlier comment, there's currently a bug).apps/api-gateway/src/ecosystem/ecosystem.controller.ts (1)
77-99: LGTM! Endpoint correctly uses both guards for role enforcement.The
getInvitationsendpoint properly applies bothAuthGuard('jwt')andOrgRolesGuardto enforce thePLATFORM_ADMINrole requirement.apps/ecosystem/src/ecosystem.service.ts (1)
40-65: LGTM! Invitation creation flow is well-structured.The method properly validates inputs, checks user existence, creates the invitation record, and sends the email notification. Good use of the repository pattern for data access.
apps/ecosystem/interfaces/ecosystem.interfaces.ts (1)
63-71: LGTM! Well-defined interfaces for ecosystem domain.The interfaces
IEcosystemInvitations,IEcosystemDetails, andIEcosystemDashboardare clearly structured and align with the Prisma schema and service layer requirements.Also applies to: 73-95
libs/common/src/response-messages/index.ts (1)
163-248: LGTM! Comprehensive response messages for ecosystem feature.The ecosystem message block covers all necessary success and error scenarios for the new feature. The structure is consistent with existing message patterns in the file.
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts
Outdated
Show resolved
Hide resolved
| @Module({ | ||
| imports: [ | ||
| ClientsModule.register([ | ||
| { | ||
| name: 'NATS_CLIENT', | ||
| transport: Transport.NATS, | ||
| options: getNatsOptions(CommonConstants.ECOSYSTEM_SERVICE, process.env.ECOSYSTEM_NKEY_SEED) | ||
| } | ||
| ]), | ||
| CommonModule, | ||
| GlobalConfigModule, | ||
| LoggerModule, | ||
| PlatformConfig, | ||
| ContextInterceptorModule, | ||
| CacheModule.register() | ||
| ], | ||
| controllers: [EcosystemController], | ||
| providers: [EcosystemService, EcosystemRepository, PrismaService, Logger, NATSClient] | ||
| }) | ||
| export class EcosystemModule {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check all references to ECOSYSTEM_NKEY_SEED and surrounding context
rg "ECOSYSTEM_NKEY_SEED" -A 5 -B 5
# Check for getNatsOptions function implementation
rg "getNatsOptions" -A 10 -B 2
# Check for environment variable validation patterns
rg "process\.env\." | head -20Repository: credebl/platform
Length of output: 50373
🏁 Script executed:
cat -n libs/common/src/nats.config.tsRepository: credebl/platform
Length of output: 991
🏁 Script executed:
# Search for .env files and environment validation
fd -name ".env*" | head -20
# Check for environment validation in GlobalConfigModule or startup
rg "ECOSYSTEM_NKEY_SEED|GlobalConfigModule" -A 5 --type ts | grep -A 5 -B 5 -i "valid\|throw\|error" | head -50
# Check for any startup validation
rg "bootstrap|startup" -A 10 --type ts | grep -i "nkey\|validate" | head -20Repository: credebl/platform
Length of output: 2469
🏁 Script executed:
# Search for GlobalConfigModule implementation
rg -l "GlobalConfigModule" | head -5 | xargs rg -A 20 "export.*GlobalConfigModule|class GlobalConfigModule"
# Search for environment variable validation
rg "process\.env\." | grep -i "require\|validate\|throw\|error" | head -20
# Find .env files using git
git ls-files | grep -E "\.env" | head -20Repository: credebl/platform
Length of output: 166
🏁 Script executed:
# Check .env.sample for ECOSYSTEM_NKEY_SEED and related docs
rg "ECOSYSTEM_NKEY_SEED|NKEY_SEED" -B 2 -A 2 .env.sample
# Also check general structure and comments about required vs optional
head -100 .env.sampleRepository: credebl/platform
Length of output: 5426
The application silently attempts unauthenticated NATS connection when ECOSYSTEM_NKEY_SEED is missing.
When ECOSYSTEM_NKEY_SEED is undefined, getNatsOptions gracefully returns options without an authenticator (see libs/common/src/nats.config.ts). The microservice will still attempt to connect to NATS but without authentication—there is no startup error or validation. While .env.sample documents this variable as required, there is no runtime enforcement. Consider adding startup validation to fail fast with a clear error if this required environment variable is missing, or explicitly document that unauthenticated connection is acceptable for your setup.
🤖 Prompt for AI Agents
In @apps/ecosystem/src/ecosystem.module.ts around lines 18 - 37, The module
currently lets ClientsModule.register call getNatsOptions with
process.env.ECOSYSTEM_NKEY_SEED which can be undefined, causing an
unauthenticated NATS connection; update EcosystemModule to validate
ECOSYSTEM_NKEY_SEED at startup and fail fast: in the module
bootstrap/constructor (or before calling ClientsModule.register) check
process.env.ECOSYSTEM_NKEY_SEED (or use a ConfigService) and throw a clear error
if missing, or alternatively change the ClientsModule.register call for
NATS_CLIENT to only register when the env var exists and otherwise skip
registration while logging a clear message; reference getNatsOptions,
ECOSYSTEM_NKEY_SEED, ClientsModule.register, NATS_CLIENT and EcosystemModule
when making the change.
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
|
@coderabbitai full-review |
|
@pranalidhanavade, I'll perform a comprehensive review of all the changes in this PR, analyzing:
I'll review the entire PR and provide detailed feedback on each component. ✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
libs/prisma-service/prisma/seed.ts (1)
243-254: Inverted condition preventsuser_org_rolescreation.The condition
if (!userId && !orgId && !orgRoleId)will only evaluate totruewhen all three arenull/undefined. However, the code inside tries to access.idon these values, which would throw. The intended logic appears to be the opposite: create the record when all entities exist.🐛 Proposed fix
- if (!userId && !orgId && !orgRoleId) { + if (userId && orgId && orgRoleId) { + const existingRole = await prisma.user_org_roles.findFirst({ + where: { + userId: userId.id, + orgId: orgId.id, + orgRoleId: orgRoleId.id + } + }); + if (existingRole) { + logger.log('Already seeding in org_roles'); + return; + } const platformOrganization = await prisma.user_org_roles.create({
🤖 Fix all issues with AI agents
In @apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts:
- Line 7: The ApiProperty example email in send-ecosystem-invitation.ts uses a
disallowed domain (awqx@yopmail.com) which conflicts with
DISALLOWED_EMAIL_DOMAIN in common.constant.ts; update the @ApiProperty({
example: ... }) value on the email field in the SendEcosystemInvitation DTO to
use a neutral allowed domain (e.g., example.com or example.org) so the example
passes domain validation and aligns with DISALLOWED_EMAIL_DOMAIN rules.
In @apps/api-gateway/src/ecosystem/ecosystem.service.ts:
- Around line 52-54: getAllEcosystems currently sends a payload with userId but
the downstream microservice method getAllEcosystems in
apps/ecosystem/src/ecosystem.service.ts does not accept or use it; either remove
the unused userId parameter from the API gateway method signature and stop
sending it in the NATS payload (update ecosystem.service.ts method
getAllEcosystems in apps/api-gateway to accept no args and call sendNatsMessage
with { } or no payload), or update the microservice getAllEcosystems to accept a
userId param and apply user-specific filtering (modify
apps/ecosystem/src/ecosystem.service.ts getAllEcosystems to accept userId and
filter results accordingly) and ensure the gateway continues sending { userId }.
In @apps/ecosystem/dtos/create-ecosystem-dto.ts:
- Around line 17-23: The description property lacks the SQL-injection guard
present on name; add the same validation decorator (e.g., @IsNotSQLInjection())
to the description field in create-ecosystem-dto.ts so both user-provided
strings have consistent SQL injection protection, keeping the existing
@Transform(trim), @IsNotEmpty, @MinLength, @MaxLength, and @IsString decorators
intact.
In @apps/ecosystem/interfaces/ecosystem.interfaces.ts:
- Around line 87-95: The IEcosystemDashboard interface declares
ecosystemLead.role and ecosystemLead.orgName as string but runtime code returns
null for missing values; update the interface so those properties accept null
(e.g., change role: string and orgName: string to role: string | null and
orgName: string | null on IEcosystemDashboard) and then fix any TypeScript
consumer errors by handling the nullable values where
IEcosystemDashboard.ecosystemLead is used.
In @apps/ecosystem/repositories/ecosystem.repository.ts:
- Around line 97-113: Replace the call to this.prisma with the
transaction-scoped prisma parameter when fetching the role (use
prisma.ecosystem_roles.findFirst with where: { name:
EcosystemRoles.ECOSYSTEM_LEAD }) so the lookup is part of the same transaction,
and add a null check for ecosystemRoleDetails before using
ecosystemRoleDetails.id (e.g., throw a descriptive error or create the missing
role) to avoid a null dereference when calling prisma.ecosystem_orgs.create.
- Around line 229-254: The variable ecosystemLeadOrg is misleading because the
code takes ecosystem.ecosystemOrgs[0] (which is the requesting org due to the
query filter) rather than the true ecosystem lead; either (A) change the query
that populates ecosystem.ecosystemOrgs so it selects the org with
ecosystemRole.name === 'ECOSYSTEM_LEAD' (or the ECOSYSTEM_LEAD constant) and
then keep the ecosystemLead mapping using ecosystemLeadOrg, or (B) if the
intention is to return the requesting org, rename ecosystemLeadOrg to
requestingOrg (or similar) and update the ecosystemLead output key to a
different name (e.g., requestingOrg) to avoid implying leadership; locate and
update the symbol ecosystemLeadOrg in ecosystem.repository.ts and adjust the
mapping that builds ecosystemLead accordingly.
In @apps/ecosystem/src/ecosystem.controller.ts:
- Around line 43-46: The payload parameter in createEcosystem is typed as {
createEcosystemDto } without a concrete type; import or define the DTO type
(e.g., CreateEcosystemDto) and change the signature to async
createEcosystem(payload: { createEcosystemDto: CreateEcosystemDto }):
Promise<IEcosystem> (or create a named interface for the message shape) so the
method and this.ecosystemService.createEcosystem receive a strongly typed DTO;
update imports accordingly and adjust any callers/tests if needed.
In @apps/ecosystem/templates/create-ecosystem.templates.ts:
- Line 15: The constructed validUrl (variable validUrl) currently points only to
generic sign-in/sign-up pages and must include identification so the invitation
can be validated; update the logic that builds validUrl to append either an
invitation token or the invitee's email as a query parameter (e.g.,
?invitationToken=<token> or ?email=<encodedEmail>) depending on what is
available, ensuring you URL-encode the email (use encodeURIComponent) and use
the token variable when present; keep using process.env.FRONT_END_URL and the
isUserExist branch but add the query param so the frontend sign-in/sign-up flows
can consume and validate the invitation.
In
@libs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql:
- Around line 62-74: The migration is missing the ecosystemId column and its FK;
add a nullable UUID column named ecosystemId to the ecosystem_invitations CREATE
TABLE (place it after "lastChangedBy" UUID NOT NULL) and then add an ALTER TABLE
to create the foreign key constraint named
ecosystem_invitations_ecosystemId_fkey referencing ecosystem(id) with ON DELETE
SET NULL ON UPDATE CASCADE so the DB matches the Prisma relation.
In @libs/prisma-service/prisma/schema.prisma:
- Around line 803-817: The email field in model ecosystem_invitations is
currently marked @unique which prevents the same email from being invited to
multiple ecosystems; replace the single-field uniqueness by either removing the
@unique on email and adding a composite unique on (email, ecosystemId) via an
@@unique([email, ecosystemId]) declaration on model ecosystem_invitations, or
simply remove the uniqueness entirely if duplicates are acceptable; also review
whether ecosystemId should be nullable—if orphaned invitations are undesired,
make ecosystemId non-optional (String without ?) so invitations always link to
an ecosystem.
In @libs/prisma-service/prisma/seed.ts:
- Around line 717-720: The early return when res.status === 409 prevents filling
local fields keycloakUserId, clientId, and clientSecret for user
(user.username); instead of returning, call the Keycloak API to fetch the
existing user by username (or use the same Keycloak client logic used to create
users) to obtain the Keycloak user id and any client credentials, then update
the local DB record (e.g., via prisma.user.update or your existing updateUser
logic) to set keycloakUserId, clientId, and clientSecret; replace the logger.log
+ return path with this fetch-and-update flow and log success or any errors.
🧹 Nitpick comments (14)
nest-cli.json (1)
200-208: Inconsistent JSON indentation.The nested properties inside the
ecosystemproject use 4-space indentation while all other projects in this file use 6-space indentation. This doesn't affect functionality but breaks formatting consistency.🔧 Suggested fix for consistent formatting
"ecosystem": { - "type": "application", - "root": "apps/ecosystem", - "entryFile": "main", - "sourceRoot": "apps/ecosystem/src", - "compilerOptions": { - "tsConfigPath": "apps/ecosystem/tsconfig.app.json" - } + "type": "application", + "root": "apps/ecosystem", + "entryFile": "main", + "sourceRoot": "apps/ecosystem/src", + "compilerOptions": { + "tsConfigPath": "apps/ecosystem/tsconfig.app.json" + } },libs/enum/src/enum.ts (1)
108-110: Consider adding additional status values.
EcosystemOrgStatusonly definesACTIVE. Typically, status enums include additional states likeINACTIVE,PENDING, orSUSPENDEDto handle lifecycle transitions. If these are planned for future iterations, this is fine for now.apps/ecosystem/src/main.ts (1)
9-9: Remove commented-out import.Dead commented code should be removed. The
nkeyAuthenticatorimport is unused since authentication is handled internally bygetNatsOptions.🧹 Remove dead code
-// import { nkeyAuthenticator } from 'nats';libs/common/src/response-messages/index.ts (1)
170-170: Minor inconsistency in error message terminology.The error message uses "organization Id" while similar messages elsewhere (e.g., line 122) use "orgId". Consider aligning with the existing pattern for consistency.
♻️ Suggested terminology alignment
- invalidOrgId: 'Invalid organization Id', + invalidOrgId: 'Invalid format for organization id',apps/ecosystem/dtos/create-ecosystem-dto.ts (2)
32-32: Consider adding validation to userId and orgId fields.The
userIdandorgIdfields lack any validation decorators, yet they appear to be critical identifiers used in business logic. Without validation, invalid or malicious values could cause runtime errors or security issues downstream.Consider adding appropriate validation such as:
@IsNotEmpty()to ensure they are provided@IsString()or@IsUUID()depending on the expected format- Input sanitization if needed
Alternatively, if these fields are populated internally (not from user input), document this clearly or make them readonly.
Also applies to: 40-40
29-29: Remove redundant @type decorator.The
@Type(() => String)decorator on line 29 is redundant sincetagsis already declared asstringand@IsString()validates the type. The@Typedecorator is typically used for complex type transformations.♻️ Remove redundant decorator
@ApiPropertyOptional() @IsOptional() @Transform(({ value }) => trim(value)) @IsString({ message: 'tag must be in string format.' }) -@Type(() => String) tags?: string;apps/ecosystem/templates/create-ecosystem.templates.ts (2)
3-14: Add validation for the email parameter.The
Consider adding email format validation at the beginning of the method:
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { throw new Error('Invalid email format provided'); }
17-21: Improve message flow for existing users.When
isUserExististrue, themessagevariable is set to an empty string (line 18), which results in an awkward sentence structure on line 48: "...to create a new ecosystem on Platform. Please log in to the platform..." followed immediately by an empty<p>${message}</p>tag on line 52.♻️ Improve message flow
const message = isUserExist - ? `` + ? `Please use the button below to log in and get started.` : `To get started, kindly register on ${process.env.PLATFORM_NAME} platform using this link:`; -const secondaryMessage = isUserExist ? `Please log in to the platform to start creating your ecosystem.` : ``; +const secondaryMessage = isUserExist ? `` : ``;This provides a smoother narrative flow for existing users.
Also applies to: 48-50
apps/ecosystem/src/ecosystem.controller.ts (1)
10-10: Logger is initialized but not used.The logger is initialized on line 10 but doesn't appear to be used in any of the controller methods. If logging is planned for future error handling or debugging, this is fine. Otherwise, consider removing it to reduce noise.
If the logger is intended for future use, consider adding log statements for key operations:
@MessagePattern({ cmd: 'create-ecosystem' }) async createEcosystem(payload: { createEcosystemDto: CreateEcosystemDto }): Promise<IEcosystem> { this.logger.log(`Creating ecosystem: ${payload.createEcosystemDto.name}`); return this.ecosystemService.createEcosystem(payload.createEcosystemDto); }apps/ecosystem/repositories/ecosystem.repository.ts (1)
117-122: Consider using Prisma'somitor explicitselectinstead of mutating the result.Mutating the returned object with
deleteworks but is less idiomatic. Using Prisma's field selection at query time is cleaner and avoids potential issues if the object is used elsewhere.♻️ Alternative approach using select
const createdEcosystem = await prisma.ecosystem.create({ data: { name, description, tags, autoEndorsement, logoUrl: logo, createdBy: userId, lastChangedBy: userId - } + }, + select: { + id: true, + name: true, + description: true, + tags: true, + autoEndorsement: true, + logoUrl: true, + createdBy: true, + createDateTime: true + } });Then remove lines 118-120.
libs/prisma-service/prisma/seed.ts (1)
541-545: Add null check forcachedConfigbefore accessing properties.If
updateClientIdis called beforegetPlatformConfig, accessingcachedConfig.platformEmailwill throw. While the currentmain()order is correct, adding a defensive check improves robustness.♻️ Proposed fix
for (const user of users) { + if (!cachedConfig) { + throw new Error('Platform config not loaded. Call getPlatformConfig first.'); + } if (user.email === cachedConfig.platformEmail) { logger.log('⚠️ Skipping update of clientId for platform admin'); continue; }apps/ecosystem/src/ecosystem.service.ts (1)
160-164: Consider using dot notation for type safety.The bracket notation
organization['ecosystemRole']['name']works but bypasses TypeScript's type checking. If theecosystemRolerelationship is properly typed, dot notation provides better IDE support and compile-time safety.♻️ Cleaner approach
for (const organization of ecoOrganizationList) { - if (organization['ecosystemRole']['name'] === EcosystemRoles.ECOSYSTEM_MEMBER) { + if (organization.ecosystemRole?.name === EcosystemRoles.ECOSYSTEM_MEMBER) { throw new ConflictException(ResponseMessages.ecosystem.error.ecosystemOrgAlready); } }apps/api-gateway/src/ecosystem/ecosystem.controller.ts (1)
125-127: Unusual bracket notation for property access.
user?.['id']is functionally equivalent touser?.idbut less conventional. If there's a TypeScript typing issue with theuserobject, consider extending the type definition instead.♻️ Cleaner approach
createEcosystemDto.orgId = orgId; - createEcosystemDto.userId = user?.['id']; + createEcosystemDto.userId = user?.id;apps/ecosystem/interfaces/ecosystem.interfaces.ts (1)
73-85: Consider nullable type fordeletedAt.The
deletedAtproperty is typed asDate, but for active (non-deleted) records, this value will benull. Consider usingDate | nullto accurately represent the data model.♻️ Proposed fix
export interface IEcosystemDetails { id: string; name: string; description: string; tags: string; createDateTime: Date; createdBy: string; lastChangedDateTime: Date; lastChangedBy: string; - deletedAt: Date; + deletedAt: Date | null; logoUrl: string; ledgers: string[]; }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (23)
.env.sampleapps/api-gateway/src/app.module.tsapps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.tsapps/api-gateway/src/ecosystem/ecosystem.controller.tsapps/api-gateway/src/ecosystem/ecosystem.module.tsapps/api-gateway/src/ecosystem/ecosystem.service.tsapps/ecosystem/dtos/create-ecosystem-dto.tsapps/ecosystem/interfaces/ecosystem.interfaces.tsapps/ecosystem/repositories/ecosystem.repository.tsapps/ecosystem/src/ecosystem.controller.tsapps/ecosystem/src/ecosystem.module.tsapps/ecosystem/src/ecosystem.service.tsapps/ecosystem/src/main.tsapps/ecosystem/templates/create-ecosystem.templates.tsapps/ecosystem/tsconfig.app.jsonlibs/common/src/common.constant.tslibs/common/src/response-messages/index.tslibs/enum/src/enum.tslibs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.jsonlibs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sqllibs/prisma-service/prisma/schema.prismalibs/prisma-service/prisma/seed.tsnest-cli.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-17T08:03:16.180Z
Learnt from: KambleSahil3
Repo: credebl/platform PR: 1518
File: libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json:11-20
Timestamp: 2025-11-17T08:03:16.180Z
Learning: In the credebl/platform repository, seed data files like libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json intentionally contain empty strings for sensitive fields (email, username, passwords, API keys, etc.) because these values are populated from .env file at runtime, not hardcoded in the JSON.
Applied to files:
libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.jsonapps/ecosystem/src/ecosystem.module.tslibs/prisma-service/prisma/seed.ts
🧬 Code graph analysis (8)
apps/api-gateway/src/ecosystem/ecosystem.module.ts (3)
apps/api-gateway/src/app.module.ts (1)
Module(40-123)apps/ecosystem/src/ecosystem.module.ts (1)
Module(18-37)libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)
apps/ecosystem/src/ecosystem.module.ts (1)
libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)
apps/ecosystem/dtos/create-ecosystem-dto.ts (3)
libs/common/src/cast.helper.ts (2)
trim(39-43)IsNotSQLInjection(96-127)libs/validations/minLength.ts (1)
MinLength(3-28)libs/validations/maxLength.ts (1)
MaxLength(3-28)
apps/api-gateway/src/ecosystem/ecosystem.service.ts (2)
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (1)
SendEcosystemCreateDto(6-13)apps/ecosystem/interfaces/ecosystem.interfaces.ts (3)
IEcosystemInvitations(63-71)IEcosystem(18-26)IEcosystemDashboard(87-95)
apps/ecosystem/repositories/ecosystem.repository.ts (2)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (2)
ICreateEcosystem(3-16)IEcosystemDashboard(87-95)libs/common/src/response-messages/index.ts (1)
ResponseMessages(1-659)
apps/ecosystem/src/main.ts (3)
libs/logger/src/logger.interface.ts (1)
Logger(6-20)libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)libs/logger/src/nestjsLoggerServiceAdapter.ts (1)
NestjsLoggerServiceAdapter(7-41)
apps/api-gateway/src/ecosystem/ecosystem.controller.ts (2)
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (1)
SendEcosystemCreateDto(6-13)libs/common/src/interfaces/response.interface.ts (1)
IResponse(8-13)
apps/ecosystem/src/ecosystem.controller.ts (1)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (3)
IEcosystemInvitations(63-71)IEcosystem(18-26)IEcosystemDashboard(87-95)
🪛 dotenv-linter (4.0.0)
.env.sample
[warning] 121-121: [UnorderedKey] The ECOSYSTEM_NKEY_SEED key should go before the ISSUANCE_NKEY_SEED key
(UnorderedKey)
[warning] 121-121: [ValueWithoutQuotes] This value needs to be surrounded in quotes
(ValueWithoutQuotes)
🔇 Additional comments (31)
libs/enum/src/enum.ts (2)
94-98: LGTM!The
EcosystemRolesenum is well-defined with clear role hierarchy (Owner, Lead, Member).
100-106: LGTM!The
EcosystemConfigSettingsenum provides appropriate configuration keys for ecosystem feature toggles.libs/prisma-service/prisma/schema.prisma (6)
39-40: LGTM!User model relations properly added for ecosystem feature integration.
160-160: LGTM!Organisation model relation properly added for ecosystem integration.
735-753: LGTM!The
ecosystemmodel is well-structured with appropriate audit fields, optional soft-delete viadeletedAt, and properly defined relations.
755-764: LGTM!The
ecosystem_rolesmodel follows the established pattern with unique name constraint.
766-780: LGTM!The
ecosystem_usersmodel correctly enforces a unique constraint on(userId, ecosystemId)to prevent duplicate user-ecosystem associations.
782-801: LGTM!The
ecosystem_orgsmodel correctly enforces a unique constraint on(orgId, ecosystemId)to prevent duplicate organization-ecosystem associations.libs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql (5)
85-86: Verify global uniqueness on email is intended.The unique index on
ecosystem_invitations.emailprevents the same email from being invited to multiple ecosystems. If this is intentional (e.g., invitations are tied to a single ecosystem creation flow), this is fine. Otherwise, consider a composite unique index.
1-17: LGTM!The
ecosystemtable is well-structured with appropriate columns, data types, and constraints.
19-29: LGTM!The
ecosystem_rolestable is properly defined with a unique constraint onname.
31-43: LGTM!The
ecosystem_userstable correctly defines the user-ecosystem association.
45-60: LGTM!The
ecosystem_orgstable properly links organizations to ecosystems with role associations..env.sample (1)
121-121: LGTM!The
ECOSYSTEM_NKEY_SEEDenvironment variable is correctly added following the pattern of other NKEY_SEED variables.Static analysis flagged ordering (should be before ISSUANCE_NKEY_SEED alphabetically) and missing quotes, but the existing NKEY_SEED variables don't follow strict alphabetical ordering and also lack quotes, so this maintains consistency with the current style.
apps/ecosystem/src/main.ts (1)
14-24: LGTM!The bootstrap function correctly initializes the ecosystem microservice with NATS transport, configures logging via
NestjsLoggerServiceAdapter, and applies the global exception filter. The pattern is consistent with other microservices in the codebase.apps/ecosystem/tsconfig.app.json (1)
1-9: LGTM!The TypeScript configuration correctly extends the root config, sets the appropriate output directory, and follows the established pattern used by other applications in the monorepo.
libs/common/src/common.constant.ts (1)
257-259: LGTM! Clean addition of ecosystem service constant.The new
ECOSYSTEM_SERVICEconstant follows the established pattern and is correctly placed in the enum. The value 'ecosystem' is used consistently across the ecosystem module configurations for NATS transport setup.apps/api-gateway/src/ecosystem/ecosystem.module.ts (1)
10-22: LGTM! Well-structured API gateway client module.The module configuration is correct:
- Uses
ECOSYSTEM_SERVICEas the queue name for routing messages to the ecosystem microservice- Uses
API_GATEWAY_NKEY_SEEDfor authentication (appropriate since this is the API gateway)- Minimal provider set is appropriate for a client-side gateway module
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (1)
8-12: Good validation implementation.The validation decorators are properly configured with clear error messages, and the
Transformdecorator ensures the email is trimmed before validation.libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json (1)
178-187: LGTM! Ecosystem role seed data is properly structured.The new
ecosystemRoleDatafollows the same pattern asorgRoleDataand provides clear role definitions for the ecosystem feature. The structure is consistent with the existing seed data format.apps/ecosystem/src/ecosystem.module.ts (1)
18-36: LGTM! Well-architected ecosystem microservice module.The module configuration is correct for a standalone microservice:
- Uses
ECOSYSTEM_SERVICEas the queue name (this service listens on this queue)- Uses
ECOSYSTEM_NKEY_SEEDfor authentication (appropriate for the ecosystem service)- Includes comprehensive data access layers (EcosystemRepository, PrismaService) which are necessary for the service implementation
- Proper separation of concerns compared to the API gateway client module
apps/api-gateway/src/app.module.ts (1)
1-76: LGTM! Module wiring is correct.The addition of
EcosystemModuleand related imports follows the established pattern in this module. All necessary imports are present, and the module is properly registered in the imports array.apps/ecosystem/repositories/ecosystem.repository.ts (1)
30-51: LGTM!The invitation creation logic is straightforward and correctly handles the nullable
invitedUserId.apps/api-gateway/src/ecosystem/ecosystem.service.ts (1)
1-63: LGTM!The gateway service correctly proxies requests to the microservice via NATS. The structure follows the established patterns in the codebase.
libs/prisma-service/prisma/seed.ts (2)
139-165: LGTM!The
createEcosystemRolesfunction follows the established pattern for seeding data with proper existence checks.
812-817: LGTM on seed execution order.The ordering of new seed steps is correct:
getPlatformConfigpopulatescachedConfigbefore functions that depend on it (updateClientId,updatePlatformUserRole,createKeycloakUser).apps/ecosystem/src/ecosystem.service.ts (2)
45-70: LGTM!The
inviteUserToCreateEcosystemmethod has proper validation, correctly handles both existing and new users, and triggers email notification.
90-128: Remove unused methods:checkUserExistInPlatformandgetUserUserId.These methods are defined in the ecosystem service but are never called. The same methods exist and are actively used in
organization.service.ts, indicating these are duplicate, dead code.apps/api-gateway/src/ecosystem/ecosystem.controller.ts (2)
41-70: LGTM!The invitation endpoint is well-structured with appropriate authorization (PLATFORM_ADMIN only), proper HTTP status codes, and consistent response format.
106-137: LGTM!The ecosystem creation endpoint correctly extracts
orgIdfrom path parameters anduserIdfrom the authenticated user, then delegates to the service layer.apps/ecosystem/interfaces/ecosystem.interfaces.ts (1)
3-16: LGTM!The
ICreateEcosysteminterface appropriately marksledgersas required while keeping other fields optional for flexible ecosystem creation scenarios.
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts
Outdated
Show resolved
Hide resolved
| const ecosystemLeadOrg = ecosystem.ecosystemOrgs?.length ? ecosystem.ecosystemOrgs[0] : null; | ||
|
|
||
| return { | ||
| ecosystem: [ | ||
| { | ||
| id: ecosystem.id, | ||
| name: ecosystem.name, | ||
| description: ecosystem.description, | ||
| tags: ecosystem.tags, | ||
| createDateTime: ecosystem.createDateTime, | ||
| createdBy: ecosystem.createdBy, | ||
| lastChangedDateTime: ecosystem.lastChangedDateTime, | ||
| lastChangedBy: ecosystem.lastChangedBy, | ||
| deletedAt: ecosystem.deletedAt, | ||
| logoUrl: ecosystem.logoUrl, | ||
| ledgers: ecosystem.ledgers as string[] | ||
| } | ||
| ], | ||
| membersCount: 0, | ||
| endorsementsCount: 0, | ||
| ecosystemLead: ecosystemLeadOrg | ||
| ? { | ||
| role: ecosystemLeadOrg.ecosystemRole?.name ?? null, | ||
| orgName: ecosystemLeadOrg.organisation?.name ?? null | ||
| } | ||
| : null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Misleading variable name: ecosystemLeadOrg may not be the actual ecosystem lead.
The query filters ecosystemOrgs by the provided orgId, so ecosystemOrgs[0] returns the requesting organization's data, not necessarily the ecosystem lead. If the intent is to show the actual ecosystem lead, the query should filter by ECOSYSTEM_LEAD role instead.
🔧 If you need the actual ecosystem lead
- const ecosystemLeadOrg = ecosystem.ecosystemOrgs?.length ? ecosystem.ecosystemOrgs[0] : null;
+ // Fetch the actual ecosystem lead separately
+ const ecosystemLeadOrg = await this.prisma.ecosystem_orgs.findFirst({
+ where: {
+ ecosystemId,
+ deletedAt: null,
+ ecosystemRole: { name: EcosystemRoles.ECOSYSTEM_LEAD }
+ },
+ include: {
+ ecosystemRole: true,
+ organisation: { select: { name: true } }
+ }
+ });Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In @apps/ecosystem/repositories/ecosystem.repository.ts around lines 229 - 254,
The variable ecosystemLeadOrg is misleading because the code takes
ecosystem.ecosystemOrgs[0] (which is the requesting org due to the query filter)
rather than the true ecosystem lead; either (A) change the query that populates
ecosystem.ecosystemOrgs so it selects the org with ecosystemRole.name ===
'ECOSYSTEM_LEAD' (or the ECOSYSTEM_LEAD constant) and then keep the
ecosystemLead mapping using ecosystemLeadOrg, or (B) if the intention is to
return the requesting org, rename ecosystemLeadOrg to requestingOrg (or similar)
and update the ecosystemLead output key to a different name (e.g.,
requestingOrg) to avoid implying leadership; locate and update the symbol
ecosystemLeadOrg in ecosystem.repository.ts and adjust the mapping that builds
ecosystemLead accordingly.
| @MessagePattern({ cmd: 'create-ecosystem' }) | ||
| async createEcosystem(payload: { createEcosystemDto }): Promise<IEcosystem> { | ||
| return this.ecosystemService.createEcosystem(payload.createEcosystemDto); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add type annotation for createEcosystemDto.
The payload parameter on line 44 has an object type with an untyped createEcosystemDto property. This reduces type safety and IDE support.
🔧 Add proper type annotation
+import { CreateEcosystemDto } from '../dtos/create-ecosystem-dto';
+
@MessagePattern({ cmd: 'create-ecosystem' })
-async createEcosystem(payload: { createEcosystemDto }): Promise<IEcosystem> {
+async createEcosystem(payload: { createEcosystemDto: CreateEcosystemDto }): Promise<IEcosystem> {
return this.ecosystemService.createEcosystem(payload.createEcosystemDto);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @MessagePattern({ cmd: 'create-ecosystem' }) | |
| async createEcosystem(payload: { createEcosystemDto }): Promise<IEcosystem> { | |
| return this.ecosystemService.createEcosystem(payload.createEcosystemDto); | |
| } | |
| import { CreateEcosystemDto } from '../dtos/create-ecosystem-dto'; | |
| @MessagePattern({ cmd: 'create-ecosystem' }) | |
| async createEcosystem(payload: { createEcosystemDto: CreateEcosystemDto }): Promise<IEcosystem> { | |
| return this.ecosystemService.createEcosystem(payload.createEcosystemDto); | |
| } |
🤖 Prompt for AI Agents
In @apps/ecosystem/src/ecosystem.controller.ts around lines 43 - 46, The payload
parameter in createEcosystem is typed as { createEcosystemDto } without a
concrete type; import or define the DTO type (e.g., CreateEcosystemDto) and
change the signature to async createEcosystem(payload: { createEcosystemDto:
CreateEcosystemDto }): Promise<IEcosystem> (or create a named interface for the
message shape) so the method and this.ecosystemService.createEcosystem receive a
strongly typed DTO; update imports accordingly and adjust any callers/tests if
needed.
libs/prisma-service/prisma/seed.ts
Outdated
| if (409 === res.status) { | ||
| logger.log(`⚠️ User ${user.username} already exists`); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Early return on 409 may leave local user record incomplete.
When Keycloak returns 409 (user exists), the function returns without updating the local database user's keycloakUserId, clientId, and clientSecret. If a previous seed run created the Keycloak user but failed before updating the local DB, subsequent runs won't fix the incomplete state.
🔧 Consider fetching the existing Keycloak user ID and updating local DB
if (409 === res.status) {
logger.log(`⚠️ User ${user.username} already exists`);
- return;
+ // Fetch existing user ID from Keycloak and update local DB
+ const searchRes = await fetch(
+ `${KEYCLOAK_DOMAIN}admin/realms/${KEYCLOAK_REALM}/users?email=${encodeURIComponent(user.email)}`,
+ {
+ headers: { Authorization: `Bearer ${token}` }
+ }
+ );
+ const existingUsers = await searchRes.json();
+ if (existingUsers?.length > 0) {
+ const keycloakUserId = existingUsers[0].id;
+ // Continue to update local DB with existing Keycloak user ID
+ // (move lines 745-759 to a shared helper)
+ }
+ return;
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In @libs/prisma-service/prisma/seed.ts around lines 717 - 720, The early return
when res.status === 409 prevents filling local fields keycloakUserId, clientId,
and clientSecret for user (user.username); instead of returning, call the
Keycloak API to fetch the existing user by username (or use the same Keycloak
client logic used to create users) to obtain the Keycloak user id and any client
credentials, then update the local DB record (e.g., via prisma.user.update or
your existing updateUser logic) to set keycloakUserId, clientId, and
clientSecret; replace the logger.log + return path with this fetch-and-update
flow and log success or any errors.
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
|
@coderabbitai full-review |
|
@pranalidhanavade, I'll perform a comprehensive review of all the changes in this PR, analyzing:
I'll review the entire PR and provide detailed feedback on each component. ✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 16
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/api-gateway/src/app.module.ts (1)
46-52: Fail fast ifprocess.env.API_GATEWAY_NKEY_SEEDis missing (prevents opaque NATS startup failures).
Right nowgetNatsOptions(..., undefined)can silently propagate to the NATS client config.Proposed fix
@@ ClientsModule.register([ { name: 'NATS_CLIENT', transport: Transport.NATS, - options: getNatsOptions(CommonConstants.API_GATEWAY_SERVICE, process.env.API_GATEWAY_NKEY_SEED) + options: getNatsOptions( + CommonConstants.API_GATEWAY_SERVICE, + (() => { + const seed = process.env.API_GATEWAY_NKEY_SEED; + if (!seed) throw new Error('Missing env: API_GATEWAY_NKEY_SEED'); + return seed; + })() + ) } ]),
🤖 Fix all issues with AI agents
In @apps/api-gateway/src/ecosystem/ecosystem.controller.ts:
- Around line 119-137: The controller mutates the incoming DTO
(createEcosystemDto) before calling ecosystemService.createEcosystem which can
break validation/transform and cause side effects; instead construct a new
payload object (e.g., const payload = { ...createEcosystemDto, orgId, userId:
user?.['id'] }) inside createNewEcosystem and pass that to
ecosystemService.createEcosystem, leaving the original createEcosystemDto
untouched and preserving intent in the response building that follows.
In @apps/ecosystem/interfaces/ecosystem.interfaces.ts:
- Around line 63-71: The IEcosystemInvitations interface has incorrect
nullability: change userId to allow null (e.g., userId?: string | null) to match
persisted data, and any soft-delete timestamp fields (deletedAt) in this file’s
interfaces (including the other interface around lines 73-85) should be typed as
Date | null (e.g., deletedAt?: Date | null); update IEcosystemInvitations and
the other interface(s) accordingly so the optional/nullable types align with
Prisma’s persisted shapes.
In @apps/ecosystem/repositories/ecosystem.repository.ts:
- Around line 131-143: The method checkEcosystemNameExist assumes
prisma.ecosystem.findFirst always returns an ecosystem but findFirst can return
null; change its return type from Promise<ecosystem> to Promise<ecosystem |
null> (or Nullable<ecosystem> depending on your types) and update any callers to
handle a possible null result; locate the method by name checkEcosystemNameExist
and the prisma call this.prisma.ecosystem.findFirst and adjust the signature and
any dependent usages accordingly.
- Around line 234-292: The return is unsafely casting ecosystem.ledgers to
string[] in getEcosystemDashboard which can produce runtime shape bugs; validate
and normalize ecosystem.ledgers before returning by checking
Array.isArray(ecosystem.ledgers) and that every item is a string (or coerce
items to strings) and default to an empty array if validation fails, then use
that normalized array instead of ecosystem.ledgers as string[].
- Around line 30-51: The createEcosystemInvitation function currently sets
status to Invitation.ACCEPTED which bypasses invite/accept flow; change the
initial status to the pending enum value (e.g., Invitation.PENDING or
equivalent) so invitations are created in a pending state and only move to
ACCEPTED when the accept flow runs; update any tests or callers expecting
ACCEPTED if needed and keep references to createEcosystemInvitation and
Invitation to locate the change.
- Around line 70-129: The code calls createNewEcosystem and then mutates the
returned Prisma object with delete statements; instead of deleting properties,
modify the prisma.$transaction flow to use prisma.ecosystem.create({ data: ...,
select: { /* only include fields to expose: id, name, description, tags,
autoEndorsement, logoUrl, createdBy, createdDateTime, ... */ } }) (and similarly
adjust any subsequent reads) so the returned value already matches the public
ecosystem shape, remove the delete
transaction.lastChangedDateTime/lastChangedBy/deletedAt lines, and ensure the
function signature or returned type aligns with the selected fields (or map the
selected result to the ecosystem type) to keep results type-safe and consistent.
In @apps/ecosystem/src/ecosystem.controller.ts:
- Around line 18-24: The createEcosystem handler’s parameter is untyped: add the
proper DTO type to the createEcosystem(createEcosystemDto) parameter (use the
existing CreateEcosystemDto type used elsewhere) so the method signature is
async createEcosystem(createEcosystemDto: CreateEcosystemDto):
Promise<IEcosystem> and update any imports; also enable global ValidationPipe
for NATS payloads in the microservice bootstrap (instantiate and apply
ValidationPipe when creating the microservice) so DTO class-validator rules are
enforced for NATS messages.
In @apps/ecosystem/src/ecosystem.service.ts:
- Around line 90-111: The catch block in checkUserExistInPlatform (and the
similar block around lines 113-128) assumes error.status exists; change it to
derive a numeric status with a safe default (e.g., const status = error?.status
?? 500) and a safe message (e.g., const message = error?.message ??
String(error)), then throw new HttpException({ status, error: message }, status)
so the HttpException always receives a valid status and a meaningful message.
- Around line 45-70: The method inviteUserToCreateEcosystem writes
invitedUser?.id ?? null into the DB but IEcosystemInvitations.userId is declared
non-null string, causing a type-contract mismatch; either make
IEcosystemInvitations.userId nullable (string | null) and update the
createEcosystemInvitation return type and any callers to handle null, or ensure
inviteUserToCreateEcosystem always supplies a non-null userId (e.g., create or
fetch a user first) and adjust createEcosystemInvitation signatures; update the
types for IEcosystemInvitations and the createEcosystemInvitation method to stay
consistent with the actual stored value.
- Around line 30-37: The constructor currently injects Logger which will fail
unless a Logger provider exists; remove Logger from the constructor parameters
and instead instantiate it inside the service class (e.g., add a private
readonly logger = new Logger(EcosystemService.name) field) and import Logger
from @nestjs/common; update references to the injected logger to use the new
class field and remove Logger from the constructor signature.
- Around line 72-88: The email subject in sendInviteEmailTemplate currently uses
process.env.PLATFORM_NAME which can be undefined; update the logic to derive a
safe platform name (e.g., use platformConfigData.platformName if available,
otherwise fall back to a sensible default like "Platform" or an empty string)
and construct emailSubject from that safe value so it never becomes "undefined"
— modify the assignment to emailData.emailSubject in sendInviteEmailTemplate to
reference this fallback.
In @apps/ecosystem/templates/create-ecosystem.templates.ts:
- Line 4: The sendInviteEmailTemplate function currently declares an unused
email parameter; either remove the unused parameter or use it in the returned
template. To fix, update sendInviteEmailTemplate(email: string, isUserExist:
boolean) to interpolate the email into the template body (e.g., include a line
like “Invited email: {email}” or personalize the greeting with the recipient
address) and ensure any conditional text that depends on isUserExist still
renders correctly, or if the email is truly unnecessary, remove the email
parameter and callers should stop passing it.
- Line 21: The FRONT_END_URL is used directly when building validUrl, so
escape/sanitize it like the other environment values to prevent potential XSS;
update the validUrl assignment (the const validUrl variable) to use the same
escaping helper used for lines where other env vars are sanitized (e.g., pass
process.env.FRONT_END_URL through the existing escape/sanitize function or use
encodeURI on it) before concatenating the path (/sign-in or /sign-up).
In
@libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json:
- Around line 178-187: The seed data is missing the "Ecosystem Owner" role
referenced by the EcosystemRoles enum (ECOSYSTEM_OWNER); update the
ecosystemRoleData array to include an object for the missing role (e.g., name
"Ecosystem Owner" and an appropriate description) so all enum members have
corresponding seed entries and avoid runtime lookups failing.
In
@libs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql:
- Around line 62-74: Add a nullable deletedAt TIMESTAMPTZ(6) column to the
ecosystem_invitations table to match the soft-delete pattern used elsewhere:
update the CREATE TABLE "ecosystem_invitations" statement to include "deletedAt"
TIMESTAMPTZ(6) NULL (default NULL) alongside the other timestamp columns so
invitations follow the same soft-delete convention as other ecosystem tables.
In @libs/prisma-service/prisma/schema.prisma:
- Around line 803-819: The model ecosystem_invitations currently has a global
@unique on email which prevents multiple invites per email across ecosystems;
replace that with a composite unique index @@unique([email, ecosystemId]) in the
ecosystem_invitations model, update the createEcosystemInvitation function to
accept an ecosystemId parameter and set ecosystemId when creating the invitation
record, propagate the new parameter to all callers of createEcosystemInvitation
so the field is populated, and wrap the Prisma create call in a try-catch to
handle and translate unique-constraint errors (e.g., detect
PrismaUniqueConstraintError or error.code) into a graceful application error.
🧹 Nitpick comments (12)
.env.sample (1)
121-121: LGTM! Environment variable added consistently.The
ECOSYSTEM_NKEY_SEEDvariable follows the same pattern as other NKEY_SEED variables in the file.Note: Static analysis suggests reordering (placing before
ISSUANCE_NKEY_SEED) and adding quotes around the value for consistency, but these are optional style preferences.libs/prisma-service/prisma/seed.ts (1)
660-764: Keycloak user creation is well-implemented with minor clarification needed.The
createKeycloakUserfunction properly handles user creation, conflict scenarios, and credential encryption. It correctly depends oncachedConfigbeing populated before execution.Minor observation: Line 705 checks
user.passwordbut the password always comes fromPLATFORM_ADMIN_USER_PASSWORDenv var (line 690). Consider simplifying this to directly check the env var for clarity.♻️ Optional clarification
- credentials: user.password - ? [ + credentials: PLATFORM_ADMIN_USER_PASSWORD + ? [ { type: 'password', - value: user.password, + value: PLATFORM_ADMIN_USER_PASSWORD, temporary: false } ] : []libs/prisma-service/prisma/schema.prisma (1)
766-801: LGTM! Ecosystem membership models are well-structured.Both
ecosystem_usersandecosystem_orgsmodels properly prevent duplicate memberships with unique composite constraints and establish correct relations.Optional: Consider using an enum for the
statusfield (line 785) instead ofStringto ensure type safety and prevent invalid status values.apps/ecosystem/src/main.ts (1)
9-9: Remove commented-out import.The commented-out
nkeyAuthenticatorimport is unused sincegetNatsOptionshandles NATS authentication internally. Remove this dead code to keep the file clean.♻️ Suggested fix
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter'; -// import { nkeyAuthenticator } from 'nats'; import { getNatsOptions } from '@credebl/common/nats.config';libs/enum/src/enum.ts (1)
108-110: Consider expanding the ecosystem organization status enum.The enum currently only defines ACTIVE status. Consider whether additional states are needed such as PENDING, INACTIVE, SUSPENDED, or REJECTED to support the full lifecycle of ecosystem organizations.
libs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql (1)
45-60: Consider adding a constraint or enum for the status field.The
statusfield is defined as TEXT without any constraints. Consider adding a CHECK constraint or using a PostgreSQL enum type to enforce valid status values and prevent invalid data entry.💡 Example with CHECK constraint
CREATE TABLE "ecosystem_orgs" ( "id" UUID NOT NULL, "orgId" UUID NOT NULL, "status" TEXT NOT NULL, + CONSTRAINT "ecosystem_orgs_status_check" CHECK (status IN ('ACTIVE', 'PENDING', 'INACTIVE')), "deploymentMode" TEXT,apps/ecosystem/templates/create-ecosystem.templates.ts (2)
5-20: Consider using a utility function for environment variable validation.Based on learnings, the team prefers creating utilities for validating required environment variables rather than implementing inline validation. This approach promotes reusability across different parts of the application.
Consider extracting this validation logic into a shared utility function that can be reused by other template classes.
18-18: Use conventional comparison syntax.The condition
0 < missingVars.lengthis unconventional. The idiomatic way to write this ismissingVars.length > 0.♻️ Proposed fix
- if (0 < missingVars.length) { + if (missingVars.length > 0) { throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`); }apps/ecosystem/dtos/create-ecosystem-dto.ts (2)
26-31: Remove redundant @type decorator.The
@Type(() => String)decorator on line 30 is redundant since@Transform(({ value }) => trim(value))on line 28 already handles type transformation, and@IsString()on line 29 validates the type.♻️ Proposed fix
@ApiPropertyOptional() @IsOptional() @Transform(({ value }) => trim(value)) @IsString({ message: 'tag must be in string format.' }) - @Type(() => String) tags?: string;
33-33: Consider adding validation for userId and orgId fields.The
userIdandorgIdfields lack validation decorators. If these values are set by the controller or service layer, consider adding appropriate validation decorators (@IsNotEmpty(),@IsUUID(), etc.) to ensure data integrity at the DTO level.If these fields are intentionally excluded from validation because they're set programmatically, consider adding comments to clarify this design decision.
Also applies to: 41-41
apps/api-gateway/src/ecosystem/ecosystem.service.ts (1)
19-59: Centralize NATS cmd strings (prevents gateway ↔ microservice drift).
Right now the contract is duplicated as raw strings in multiple places.Example direction
+// e.g. libs/common/src/nats/ecosystem.cmd.ts +export const ECOSYSTEM_CMDS = { + INVITE_CREATE: 'invite-user-for-ecosystem-creation', + GET_INVITES_BY_USER: 'get-ecosystem-invitations-by-user', + CREATE: 'create-ecosystem', + GET_ALL: 'get-all-ecosystems', + DASHBOARD: 'get-ecosystem-dashboard' +} as const;- return this.natsClient.sendNatsMessage(this.serviceProxy, 'create-ecosystem', payload); + return this.natsClient.sendNatsMessage(this.serviceProxy, ECOSYSTEM_CMDS.CREATE, payload);apps/ecosystem/interfaces/ecosystem.interfaces.ts (1)
27-61: Avoid re-definingOrgAgent/LedgerDetailsin multiple domains (drift risk).
There are already similarOrgAgentinterfaces elsewhere (per provided snippets). Prefer a shared type from a common lib (or re-export) so changes don’t desync.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
.env.sampleapps/api-gateway/src/app.module.tsapps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.tsapps/api-gateway/src/ecosystem/ecosystem.controller.tsapps/api-gateway/src/ecosystem/ecosystem.module.tsapps/api-gateway/src/ecosystem/ecosystem.service.tsapps/ecosystem/dtos/create-ecosystem-dto.tsapps/ecosystem/interfaces/ecosystem.interfaces.tsapps/ecosystem/repositories/ecosystem.repository.tsapps/ecosystem/src/ecosystem.controller.tsapps/ecosystem/src/ecosystem.module.tsapps/ecosystem/src/ecosystem.service.tsapps/ecosystem/src/main.tsapps/ecosystem/templates/create-ecosystem.templates.tsapps/ecosystem/tsconfig.app.jsonlibs/common/src/common.constant.tslibs/common/src/response-messages/index.tslibs/enum/src/enum.tslibs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.jsonlibs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sqllibs/prisma-service/prisma/migrations/20260108141409_added_deleted_at_parameter_in_ecosystem_invitation/migration.sqllibs/prisma-service/prisma/schema.prismalibs/prisma-service/prisma/seed.tsnest-cli.json
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-17T08:03:16.180Z
Learnt from: KambleSahil3
Repo: credebl/platform PR: 1518
File: libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json:11-20
Timestamp: 2025-11-17T08:03:16.180Z
Learning: In the credebl/platform repository, seed data files like libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json intentionally contain empty strings for sensitive fields (email, username, passwords, API keys, etc.) because these values are populated from .env file at runtime, not hardcoded in the JSON.
Applied to files:
libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.jsonapps/ecosystem/templates/create-ecosystem.templates.tslibs/prisma-service/prisma/seed.tsapps/ecosystem/src/ecosystem.module.ts
📚 Learning: 2025-06-24T11:15:29.468Z
Learnt from: tipusinghaw
Repo: credebl/platform PR: 1297
File: apps/api-gateway/src/tracer.ts:24-28
Timestamp: 2025-06-24T11:15:29.468Z
Learning: In the credebl/platform repository, the team prefers to create utilities for validating required environment variables rather than implementing inline validation. This approach promotes reusability across different parts of the application.
Applied to files:
apps/ecosystem/templates/create-ecosystem.templates.ts
🧬 Code graph analysis (8)
apps/ecosystem/src/main.ts (3)
libs/logger/src/logger.interface.ts (1)
Logger(6-20)libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)libs/logger/src/nestjsLoggerServiceAdapter.ts (1)
NestjsLoggerServiceAdapter(7-41)
apps/ecosystem/templates/create-ecosystem.templates.ts (1)
libs/common/src/common.utils.ts (1)
escapeHtml(149-156)
apps/api-gateway/src/ecosystem/ecosystem.module.ts (3)
apps/api-gateway/src/app.module.ts (1)
Module(40-123)apps/ecosystem/src/ecosystem.module.ts (1)
Module(18-37)libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)
apps/ecosystem/dtos/create-ecosystem-dto.ts (3)
libs/common/src/cast.helper.ts (2)
trim(39-43)IsNotSQLInjection(96-127)libs/validations/minLength.ts (1)
MinLength(3-28)libs/validations/maxLength.ts (1)
MaxLength(3-28)
apps/api-gateway/src/ecosystem/ecosystem.service.ts (1)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (3)
IEcosystemInvitations(63-71)IEcosystem(18-26)IEcosystemDashboard(87-95)
apps/ecosystem/src/ecosystem.controller.ts (1)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (3)
IEcosystemInvitations(63-71)IEcosystem(18-26)IEcosystemDashboard(87-95)
apps/ecosystem/src/ecosystem.module.ts (2)
apps/api-gateway/src/ecosystem/ecosystem.module.ts (1)
Module(10-23)libs/common/src/nats.config.ts (1)
getNatsOptions(4-28)
apps/ecosystem/interfaces/ecosystem.interfaces.ts (4)
apps/api-gateway/src/issuance/utils/helper.ts (1)
JsonValue(5-5)apps/connection/src/interfaces/connection.interfaces.ts (1)
OrgAgent(111-126)apps/issuance/interfaces/issuance.interfaces.ts (1)
OrgAgent(269-284)apps/ledger/src/interfaces/ledgers.interface.ts (1)
LedgerDetails(1-6)
🪛 dotenv-linter (4.0.0)
.env.sample
[warning] 121-121: [UnorderedKey] The ECOSYSTEM_NKEY_SEED key should go before the ISSUANCE_NKEY_SEED key
(UnorderedKey)
[warning] 121-121: [ValueWithoutQuotes] This value needs to be surrounded in quotes
(ValueWithoutQuotes)
🔇 Additional comments (30)
nest-cli.json (1)
200-208: LGTM! Ecosystem project configuration follows monorepo conventions.The configuration properly defines the new ecosystem microservice with all required fields matching the pattern used by other services in the monorepo.
libs/common/src/response-messages/index.ts (1)
163-186: LGTM! Comprehensive ecosystem response messages.The ecosystem response messages follow the established pattern and provide clear, actionable feedback for both success and error scenarios. The messages cover a wide range of use cases including validation, not found errors, duplicates, and missing required fields.
libs/prisma-service/prisma/seed.ts (7)
1-31: LGTM! New imports and caching mechanism added appropriately.The new imports support encryption (CryptoJS), promise utilities (util), and platform constants. The module-level
cachedConfigvariable provides an in-memory cache for platform configuration to avoid repeated database queries.
139-165: LGTM! Ecosystem roles seeding follows established patterns.The
createEcosystemRolesfunction properly checks for existing records before creating new ones and follows the same pattern as other seeding functions in this file.
515-571: LGTM! Client ID migration logic is well-structured.The
updateClientIdfunction properly:
- Validates required environment variables
- Encrypts the new client ID once for efficiency
- Skips platform admin users
- Handles decryption errors gracefully
- Only updates users with the old client ID
The dependency on
cachedConfig.platformEmail(line 542) is safe becausegetPlatformConfig()is called before this function in the main sequence (line 814).
573-626: LGTM! Platform user role update is properly validated.The
updatePlatformUserRolefunction ensures the platform admin has the correct organization role with proper validation and idempotent behavior. The dependency oncachedConfigis safe as it's called aftergetPlatformConfig()in the main sequence.
628-658: LGTM! Keycloak token retrieval is properly implemented.The
getKeycloakTokenfunction includes comprehensive validation, proper error handling with descriptive messages, and validates the response structure before returning the access token.
772-795: LGTM! Platform config retrieval with efficient caching.The
getPlatformConfigfunction implements a simple but effective caching mechanism to avoid repeated database queries, with proper validation of required fields.
797-818: LGTM! Main seeding sequence properly orchestrated.The main function correctly orders the seeding operations, ensuring
getPlatformConfig()(line 814) is called before functions that depend oncachedConfig(lines 815-817). The new ecosystem roles seeding (line 804) and platform config creation (line 812) are properly integrated into the sequence.libs/prisma-service/prisma/schema.prisma (3)
39-40: LGTM! Ecosystem relations properly added to existing models.The new relations on the
userandorganisationmodels establish proper bidirectional links to the new ecosystem entities, following Prisma conventions.Also applies to: 160-160
755-764: LGTM! Ecosystem roles model follows established patterns.The
ecosystem_rolesmodel is properly structured as a lookup table with a unique constraint on the role name, following the same pattern as theorg_rolesmodel.
735-753: Clarify the intentional design of theledgersfield.The
ecosystemmodel definesledgersasJson?(line 752), which differs from other models in the schema that reference theledgerstable through foreign key relations (e.g.,ledgers ledgers? @relation(fields: [ledgerId], references: [id])). The ecosystem service code casts this field asstring[], suggesting it stores ledger IDs as JSON.Is this design intentional, or should the ecosystem model use a relational reference like other models? If storing ledger data as JSON is required for ecosystem-specific flexibility, consider documenting this design choice.
libs/prisma-service/prisma/migrations/20260108141409_added_deleted_at_parameter_in_ecosystem_invitation/migration.sql (1)
1-6: LGTM!The migration correctly adds soft-delete support (
deletedAt) and establishes the ecosystem relationship with appropriate cascade behavior (ON DELETE SET NULLpreserves invitation history when an ecosystem is deleted).libs/common/src/common.constant.ts (1)
257-259: LGTM!The
ECOSYSTEM_SERVICEconstant follows the established naming convention and is correctly placed within the constants file. It aligns with existing microservice identifiers used throughout the codebase.apps/api-gateway/src/ecosystem/ecosystem.module.ts (1)
10-23: LGTM!The module correctly configures the NATS client to target the
ECOSYSTEM_SERVICEqueue while using the API gateway's own authentication credentials (API_GATEWAY_NKEY_SEED). This follows the established service-to-service communication pattern in the codebase.apps/ecosystem/tsconfig.app.json (1)
1-9: LGTM!The TypeScript configuration follows the established conventions for NestJS applications in this monorepo, with appropriate output directory and exclusion patterns.
apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts (1)
6-13: LGTM!The DTO has proper validation with meaningful error messages. The
Transformdecorator correctly trims whitespace before validation occurs (class-transformer runs before class-validator).apps/ecosystem/src/ecosystem.module.ts (1)
18-37: LGTM!The module is well-structured with appropriate dependencies for a NestJS microservice. The NATS configuration correctly uses
ECOSYSTEM_NKEY_SEEDfor this service's authentication.Note:
CacheModule.register()uses the default in-memory cache, which is consistent with most microservices in the codebase. If persistent or distributed caching is needed across instances in the future, consider configuring a Redis-backed cache store (e.g.,CacheModule.register({ host: process.env.REDIS_HOST, port: process.env.REDIS_PORT })), as demonstrated in the notification module.apps/ecosystem/src/main.ts (1)
14-24: Bootstrap implementation looks correct.The microservice bootstrap follows the established pattern. Note that if
ECOSYSTEM_NKEY_SEEDis undefined, NATS will connect without authentication pergetNatsOptionsbehavior—ensure this is intentional for your deployment environment.libs/enum/src/enum.ts (2)
94-98: LGTM!The ecosystem roles enum is well-defined with clear naming conventions.
100-106: LGTM!The ecosystem configuration settings enum comprehensively covers the necessary configuration options.
libs/prisma-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql (4)
2-17: LGTM!The ecosystem table structure is well-designed with appropriate fields, constraints, and audit columns.
19-29: LGTM!The ecosystem_roles table structure is appropriate with a unique constraint on the name field.
31-43: LGTM!The ecosystem_users junction table correctly implements a many-to-many relationship with appropriate unique constraints and audit fields.
76-104: LGTM!The indexes and foreign key constraints are well-designed. The use of ON DELETE SET NULL for ecosystem_invitations.userId is appropriate since invitations should remain for audit purposes even if the user is deleted.
apps/ecosystem/templates/create-ecosystem.templates.ts (1)
29-86: LGTM!The HTML email template is well-structured with proper styling, responsive design considerations, and appropriate use of escaped variables for security.
apps/ecosystem/dtos/create-ecosystem-dto.ts (2)
8-15: LGTM!The name field validation is comprehensive and includes appropriate guards against SQL injection, length constraints, and type validation.
17-24: LGTM!The description field validation is thorough with appropriate constraints and security checks.
apps/api-gateway/src/ecosystem/ecosystem.controller.ts (1)
106-118: No changes needed. TheOrgRolesGuardcorrectly binds authorization to the:orgIdroute parameter. The implementation validates that the user has membership in the specific organization (line 60 matchesorgIdto user'suserOrgRoles), and enforces access denial if the user is not a member of that org (lines 63-65). Role validation is org-scoped (line 47 retrieves roles for the specificorgId).apps/api-gateway/src/app.module.ts (1)
1-4: No action needed.ConditionalModule.registerWhenis a fully supported API in@nestjs/configv4.0.2 and is correctly implemented in your codebase (lines 73–75). The NATS seed configuration also handles the optionalAPI_GATEWAY_NKEY_SEEDparameter gracefully—if absent, the client is initialized without authentication.
| async createNewEcosystem( | ||
| @Body() createEcosystemDto: CreateEcosystemDto, | ||
| @Param('orgId') orgId: string, | ||
| @User() user: user, | ||
| @Res() res: Response | ||
| ): Promise<Response> { | ||
| createEcosystemDto.orgId = orgId; | ||
| createEcosystemDto.userId = user?.['id']; | ||
|
|
||
| const ecosystem = await this.ecosystemService.createEcosystem(createEcosystemDto); | ||
|
|
||
| const finalResponse: IResponse = { | ||
| statusCode: HttpStatus.CREATED, | ||
| message: ResponseMessages.ecosystem.success.create, | ||
| data: ecosystem | ||
| }; | ||
|
|
||
| return res.status(HttpStatus.CREATED).json(finalResponse); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid mutating request DTOs; build a new payload object for service call.
Mutating createEcosystemDto can cause surprises with validation/transform and makes the controller harder to reason about.
Proposed fix
@@
): Promise<Response> {
- createEcosystemDto.orgId = orgId;
- createEcosystemDto.userId = user?.['id'];
-
- const ecosystem = await this.ecosystemService.createEcosystem(createEcosystemDto);
+ const ecosystem = await this.ecosystemService.createEcosystem({
+ ...createEcosystemDto,
+ orgId,
+ userId: user?.id
+ });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async createNewEcosystem( | |
| @Body() createEcosystemDto: CreateEcosystemDto, | |
| @Param('orgId') orgId: string, | |
| @User() user: user, | |
| @Res() res: Response | |
| ): Promise<Response> { | |
| createEcosystemDto.orgId = orgId; | |
| createEcosystemDto.userId = user?.['id']; | |
| const ecosystem = await this.ecosystemService.createEcosystem(createEcosystemDto); | |
| const finalResponse: IResponse = { | |
| statusCode: HttpStatus.CREATED, | |
| message: ResponseMessages.ecosystem.success.create, | |
| data: ecosystem | |
| }; | |
| return res.status(HttpStatus.CREATED).json(finalResponse); | |
| } | |
| async createNewEcosystem( | |
| @Body() createEcosystemDto: CreateEcosystemDto, | |
| @Param('orgId') orgId: string, | |
| @User() user: user, | |
| @Res() res: Response | |
| ): Promise<Response> { | |
| const ecosystem = await this.ecosystemService.createEcosystem({ | |
| ...createEcosystemDto, | |
| orgId, | |
| userId: user?.id | |
| }); | |
| const finalResponse: IResponse = { | |
| statusCode: HttpStatus.CREATED, | |
| message: ResponseMessages.ecosystem.success.create, | |
| data: ecosystem | |
| }; | |
| return res.status(HttpStatus.CREATED).json(finalResponse); | |
| } |
🤖 Prompt for AI Agents
In @apps/api-gateway/src/ecosystem/ecosystem.controller.ts around lines 119 -
137, The controller mutates the incoming DTO (createEcosystemDto) before calling
ecosystemService.createEcosystem which can break validation/transform and cause
side effects; instead construct a new payload object (e.g., const payload = {
...createEcosystemDto, orgId, userId: user?.['id'] }) inside createNewEcosystem
and pass that to ecosystemService.createEcosystem, leaving the original
createEcosystemDto untouched and preserving intent in the response building that
follows.
| export interface IEcosystemInvitations { | ||
| id: string; | ||
| email: string; | ||
| status: string; | ||
| ecosystemId?: string; | ||
| userId: string; | ||
| createDateTime: Date; | ||
| createdBy: string; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix nullability mismatches (userId, deletedAt) to match persisted data.
Repository writes userId nullable; Prisma soft-delete fields are typically Date | null.
Proposed fix
export interface IEcosystemInvitations {
@@
- userId: string;
+ userId: string | null;
@@
export interface IEcosystemDetails {
@@
- deletedAt: Date;
+ deletedAt: Date | null;Also applies to: 73-85
🤖 Prompt for AI Agents
In @apps/ecosystem/interfaces/ecosystem.interfaces.ts around lines 63 - 71, The
IEcosystemInvitations interface has incorrect nullability: change userId to
allow null (e.g., userId?: string | null) to match persisted data, and any
soft-delete timestamp fields (deletedAt) in this file’s interfaces (including
the other interface around lines 73-85) should be typed as Date | null (e.g.,
deletedAt?: Date | null); update IEcosystemInvitations and the other
interface(s) accordingly so the optional/nullable types align with Prisma’s
persisted shapes.
| async createEcosystemInvitation(payload: { | ||
| email: string; | ||
| invitedUserId: string | null; | ||
| platformAdminId: string; | ||
| }): Promise<ecosystem_invitations> { | ||
| const { email, invitedUserId, platformAdminId } = payload; | ||
|
|
||
| return this.prisma.ecosystem_invitations.create({ | ||
| data: { | ||
| email, | ||
| // Change to PENDING when accept/reject flow is ready | ||
| status: Invitation.ACCEPTED, | ||
|
|
||
| // invited user (nullable) | ||
| userId: invitedUserId, | ||
|
|
||
| // platform admin | ||
| createdBy: platformAdminId, | ||
| lastChangedBy: platformAdminId | ||
| } | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invitation status is set to ACCEPTED at creation (likely bypasses accept/reject semantics).
If this is intentional for MVP, fine; otherwise it breaks expected “invite then accept” flow and weakens the “invitationRequired” check later.
Proposed fix (if enum supports it)
@@
- // Change to PENDING when accept/reject flow is ready
- status: Invitation.ACCEPTED,
+ status: Invitation.PENDING,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async createEcosystemInvitation(payload: { | |
| email: string; | |
| invitedUserId: string | null; | |
| platformAdminId: string; | |
| }): Promise<ecosystem_invitations> { | |
| const { email, invitedUserId, platformAdminId } = payload; | |
| return this.prisma.ecosystem_invitations.create({ | |
| data: { | |
| email, | |
| // Change to PENDING when accept/reject flow is ready | |
| status: Invitation.ACCEPTED, | |
| // invited user (nullable) | |
| userId: invitedUserId, | |
| // platform admin | |
| createdBy: platformAdminId, | |
| lastChangedBy: platformAdminId | |
| } | |
| }); | |
| } | |
| async createEcosystemInvitation(payload: { | |
| email: string; | |
| invitedUserId: string | null; | |
| platformAdminId: string; | |
| }): Promise<ecosystem_invitations> { | |
| const { email, invitedUserId, platformAdminId } = payload; | |
| return this.prisma.ecosystem_invitations.create({ | |
| data: { | |
| email, | |
| status: Invitation.PENDING, | |
| // invited user (nullable) | |
| userId: invitedUserId, | |
| // platform admin | |
| createdBy: platformAdminId, | |
| lastChangedBy: platformAdminId | |
| } | |
| }); | |
| } |
🤖 Prompt for AI Agents
In @apps/ecosystem/repositories/ecosystem.repository.ts around lines 30 - 51,
The createEcosystemInvitation function currently sets status to
Invitation.ACCEPTED which bypasses invite/accept flow; change the initial status
to the pending enum value (e.g., Invitation.PENDING or equivalent) so
invitations are created in a pending state and only move to ACCEPTED when the
accept flow runs; update any tests or callers expecting ACCEPTED if needed and
keep references to createEcosystemInvitation and Invitation to locate the
change.
libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json
Show resolved
Hide resolved
...a-service/prisma/migrations/20260106131405_send_invitation_to_create_ecosystem/migration.sql
Show resolved
Hide resolved
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
|
788869f
into
feat/platform_admin_and_ecosystem
) * feat/add script to add platform admin keycloak and role Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/eslint issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/coderabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/changes to fetch value from db Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: ecosystem service and create ecosystem invitation API route Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: get all invitations api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: removed userId parameter from send invitation and get invitation api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: create and get ecosystem api routes Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warning Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings and suggestions Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings resolved Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolved comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolve comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolve comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> Co-authored-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
) * feat/add script to add platform admin keycloak and role Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/eslint issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/coderabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/changes to fetch value from db Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: ecosystem service and create ecosystem invitation API route Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: get all invitations api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: removed userId parameter from send invitation and get invitation api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: create and get ecosystem api routes Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warning Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings and suggestions Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings resolved Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolved comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolve comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolve comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> Co-authored-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
* feat: ecosystem service and create ecosystem invitation API route (#1540) * feat/add script to add platform admin keycloak and role Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/eslint issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/coderabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/changes to fetch value from db Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: ecosystem service and create ecosystem invitation API route Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: get all invitations api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: removed userId parameter from send invitation and get invitation api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: create and get ecosystem api routes Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warning Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings and suggestions Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings resolved Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolved comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolve comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolve comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> Co-authored-by: sujitaw <sujit.sutar@ayanworks.com> * feat: Add script to add platform admin to keycloak and create user org roles (#1538) * feat/add script to add platform admin keycloak and role Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/eslint issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/coderabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/changes to fetch value from db Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix pr comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix pr comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: ecosystem member invitation and management API's (#1545) * feat/add script to add platform admin keycloak and role Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/eslint issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/coderabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: ecosystem service and create ecosystem invitation API route Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: get all invitations api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * wip Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * wip completed invite member and update status for invitation Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * wip Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * wip Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat/added ecosystem invitation workflow apis Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/code rabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/minor typo issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/ pr comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/pr comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> Co-authored-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix/version for nest-cli Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: add dockerfile for ecosystem Signed-off-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com> * feat: add ecosystemt in github actions workflow Signed-off-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com> * feat: create intent API endpoints and intent template mapping APIs (#1547) * feat: create intent APIs Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: create intent mapping and create intent APIs Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: sonarlint issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: move validations from ecosystem repository to ecosystem service Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: sonarlint issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: sonarlint issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: sonarlint issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit suggestions Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> --------- Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: resloved issue for docker build (#1549) Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: Enable/disable ecosystem (#1550) * refactor: added isEcosystemEnabled flag in database in platform_config table Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: enable/disable ecosystem feature from database Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit suggestions Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: enable/disable ecosystem feature and delete intent API issue Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * coderabbit comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> --------- Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix/code rabbit issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/code rabbit issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> Signed-off-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com> Co-authored-by: sujitaw <sujit.sutar@ayanworks.com> Co-authored-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com>
* feat: ecosystem service and create ecosystem invitation API route (#1540) * feat/add script to add platform admin keycloak and role Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/eslint issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/coderabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/changes to fetch value from db Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: ecosystem service and create ecosystem invitation API route Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: get all invitations api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: removed userId parameter from send invitation and get invitation api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: create and get ecosystem api routes Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warning Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings and suggestions Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings resolved Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolved comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolve comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * resolve comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> Co-authored-by: sujitaw <sujit.sutar@ayanworks.com> * feat: Add script to add platform admin to keycloak and create user org roles (#1538) * feat/add script to add platform admin keycloak and role Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/eslint issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/coderabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/changes to fetch value from db Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix pr comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix pr comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: ecosystem member invitation and management API's (#1545) * feat/add script to add platform admin keycloak and role Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/eslint issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/coderabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: ecosystem service and create ecosystem invitation API route Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit warnings Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: get all invitations api Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * wip Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * wip completed invite member and update status for invitation Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * wip Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * wip Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat/added ecosystem invitation workflow apis Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/code rabbit comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/minor typo issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/ pr comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/pr comments Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> Co-authored-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix/version for nest-cli Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * feat: add dockerfile for ecosystem Signed-off-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com> * feat: add ecosystemt in github actions workflow Signed-off-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com> * feat: create intent API endpoints and intent template mapping APIs (#1547) * feat: create intent APIs Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * feat: create intent mapping and create intent APIs Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: sonarlint issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: move validations from ecosystem repository to ecosystem service Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: sonarlint issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: sonarlint issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: sonarlint issues Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit suggestions Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> --------- Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: resloved issue for docker build (#1549) Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: Enable/disable ecosystem (#1550) * refactor: added isEcosystemEnabled flag in database in platform_config table Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: enable/disable ecosystem feature from database Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix: coderabbit suggestions Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * refactor: enable/disable ecosystem feature and delete intent API issue Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * coderabbit comments on PR Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> --------- Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> * fix/code rabbit issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> * fix/code rabbit issue Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> --------- Signed-off-by: sujitaw <sujit.sutar@ayanworks.com> Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com> Signed-off-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com> Co-authored-by: sujitaw <sujit.sutar@ayanworks.com> Co-authored-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com>



What
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.