Skip to content

Conversation

@pranalidhanavade
Copy link
Contributor

@pranalidhanavade pranalidhanavade commented Jan 21, 2026

What

  • feat: create intent API endpoints and intent template mapping APIs

Summary by CodeRabbit

  • New Features

    • Full intent and intent-template management added to ecosystem (create/read/update/delete/query); platform endpoints for invitations, QR codes and network URL retrieval added.
  • Refactor

    • Intent-template CRUD relocated to ecosystem; invitation flows consolidated under platform.
    • Ecosystem creation route changed to POST .../create.
    • Utilities cleaned up: intent-template CRUD removed.
  • Chores

    • Database schema updated to link intents to ecosystems; new ecosystem success messages added.

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

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
@pranalidhanavade pranalidhanavade self-assigned this Jan 21, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

Important

Review skipped

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

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

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

📝 Walkthrough

Walkthrough

Moves intent-template CRUD into the ecosystem domain, adds full intent and intent-template CRUD/query surfaces across API Gateway, Ecosystem services and repository, updates Prisma schema (ecosystemId on intents), and restores/extends platform invitation and ledger endpoints. (48 words)

Changes

Cohort / File(s) Summary
API Gateway — Ecosystem
apps/api-gateway/src/ecosystem/ecosystem.controller.ts, apps/api-gateway/src/ecosystem/ecosystem.service.ts
Added HTTP endpoints for intent-templates and intents (create/list/get/update/delete), DTO imports and Swagger metadata; changed ecosystem creation route to POST /:orgId/create; removed invitation endpoints.
API Gateway — Platform
apps/api-gateway/src/platform/platform.controller.ts, apps/api-gateway/src/platform/platform.service.ts
Reintroduced platform invitation endpoints (POST/GET /invitations), added ledger/cred-def/schema/network URL/QR endpoints, admin guards, and service NATS methods for invitations.
Utilities (removed surface)
apps/api-gateway/src/utilities/utilities.controller.ts, apps/api-gateway/src/utilities/utilities.service.ts, apps/utility/src/utilities.controller.ts, apps/utility/src/utilities.repository.ts, apps/utility/src/utilities.service.ts
Removed intent-template CRUD handlers and related DTOs/repository/service methods from utilities; retained URL shortening and store-object endpoints.
Ecosystem app — Controller/Service/Repo
apps/ecosystem/src/ecosystem.controller.ts, apps/ecosystem/src/ecosystem.service.ts, apps/ecosystem/repositories/ecosystem.repository.ts
Implemented message-pattern handlers, service logic, and repository CRUD/query methods for intents and intent-templates (pagination, search, org-aware lookups, validation, ownership checks, logging).
DTOs — Intents
apps/ecosystem/dtos/intent-base.dto.ts, apps/ecosystem/dtos/create-intent.dto.ts, apps/ecosystem/dtos/update-intent.dto.ts
Added IntentBaseDto (validated name/description), CreateIntentDto and UpdateIntentDto with ecosystem/user identifiers and Swagger metadata.
Database — Prisma
libs/prisma-service/prisma/schema.prisma, libs/prisma-service/prisma/migrations/..._intent_table_creation/migration.sql
Added ecosystemId UUID FK to intents and relationship to ecosystem; migration adds non-null column and FK constraint.
Response messages
libs/common/src/response-messages/index.ts
Added new ecosystem success message keys (fetchAllEcosystems, intentCreated, intentUpdated, deleteIntent, fetchIntents, fetchIntentTemplates, fetchVerificationTemplates).
Lint/Seed minor
libs/prisma-service/prisma/seed.ts
Added ESLint camelcase disable pragma (cosmetic).

Sequence Diagram(s)

sequenceDiagram
  participant Client as "Client"
  participant API as "API Gateway (Ecosystem Controller)"
  participant Svc as "Ecosystem Service"
  participant Repo as "Ecosystem Repository"
  participant DB as "Database (Prisma)"

  Client->>API: HTTP request (intent/template CRUD)
  API->>Svc: validate & forward DTO
  Svc->>Repo: perform create/read/update/delete
  Repo->>DB: SQL via Prisma
  DB-->>Repo: result
  Repo-->>Svc: return data or error
  Svc-->>API: standardized response / error
  API-->>Client: HTTP response
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

Suggested Labels

feature

Suggested Reviewers

  • sujitaw
  • GHkrishna
  • shitrerohit

Poem

🐰 Hopped from utils into ecosystem light,
Templates and intents now take flight,
Invitations landed on platform ground,
CRUD and queries neatly found,
I nibble code and give a happy bite. 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and specifically describes the main changes: adding intent API endpoints and intent template mapping APIs, which directly aligns with the extensive additions of intent and template CRUD operations across multiple controllers and services.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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.

❤️ Share

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

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
…vice

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>
@pranalidhanavade
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@pranalidhanavade
Copy link
Contributor Author

@coderabbitai full-review

@coderabbitai
Copy link

coderabbitai bot commented Jan 22, 2026

@pranalidhanavade: I'll perform a full review of all the changes in this PR.

✅ Actions performed

Full review triggered.

@pranalidhanavade
Copy link
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link

coderabbitai bot commented Jan 22, 2026

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🤖 Fix all issues with AI agents
In `@apps/api-gateway/src/ecosystem/ecosystem.controller.ts`:
- Line 506: Add Nest's ParseUUIDPipe to validate UUID path params: update the
handler signature for getIntentTemplatesByIntentId to use `@Param`('intentId', new
ParseUUIDPipe()) intentId: string (and likewise add new ParseUUIDPipe() to any
other handlers that accept UUIDs—the ones referenced that accept orgId or id).
Import ParseUUIDPipe from `@nestjs/common` at the top of the file and apply the
same change to the other endpoints that take orgId/id so all path params are
consistently validated.
- Around line 737-738: Add UUID validation to the ecosystemId and intentId route
parameters by applying NestJS's ParseUUIDPipe (or equivalent UUID validation) to
the `@Param` decorators used in the intent handlers (e.g., the update and delete
intent methods that currently declare `@Param`('ecosystemId') ecosystemId: string
and `@Param`('intentId') intentId: string); update both parameter declarations
(also at the other occurrence noted) to use the ParseUUIDPipe so invalid UUIDs
are rejected before handler logic runs.
- Around line 625-627: The `@Roles`(OrgRoles.OWNER, OrgRoles.ADMIN) decorator on
the Post('/intents/:ecosystemId') handler is not enforced because OrgRolesGuard
is not applied; update the UseGuards on that handler (or controller) to include
OrgRolesGuard alongside AuthGuard('jwt') (e.g., UseGuards(AuthGuard('jwt'),
OrgRolesGuard)), and add the necessary import for OrgRolesGuard so the role
checks are executed for the method handling intents.
- Around line 410-412: The intent-template endpoints in ecosystem.controller.ts
(routes like POST '/intent-templates' and the related GET/PUT/DELETE handlers)
only use AuthGuard('jwt') and must enforce role-based access like the other
ecosystem endpoints; add `@Roles`(...) decorators with the appropriate roles
(e.g., Roles(Role.ADMIN, Role.SUPER_ADMIN) or whatever role set your repo uses)
to each intent-template handler, ensure RolesGuard is applied (e.g.,
`@UseGuards`(AuthGuard('jwt'), RolesGuard)), and add the necessary imports (Roles
decorator, RolesGuard, and Role enum) to the file so the
create/read/update/delete intent-template routes are protected consistently.

In `@apps/api-gateway/src/ecosystem/ecosystem.service.ts`:
- Around line 135-141: deleteIntentTemplate and getIntentTemplatesByOrgId are
sending raw strings to sendNatsMessage, causing payload format inconsistency;
update both methods to pass an object payload (e.g., { id: id } and { orgId:
orgId } or use shorthand { id } / { orgId }) to match the other calls to
natsClient.sendNatsMessage(this.serviceProxy, ...), so modify
deleteIntentTemplate and getIntentTemplatesByOrgId to wrap their string args in
objects before calling sendNatsMessage.

In `@apps/ecosystem/dtos/create-intent.dto.ts`:
- Around line 1-7: CreateIntentDto is missing DTO-level validation and Swagger
metadata for the required fields ecosystemId and userId; update the class
(extending IntentBaseDto) to add validation decorators (e.g., `@IsString` and
`@IsNotEmpty`) to both ecosystemId and userId and annotate each with Swagger
decorators (e.g., `@ApiProperty` with description and required: true) so they
match IntentBaseDto patterns and appear in generated docs even though values are
set by the controller.

In `@apps/ecosystem/dtos/update-intent.dto.ts`:
- Around line 1-8: UpdateIntentDto is missing validation and Swagger metadata
for intentId, ecosystemId, and userId; add class-validator decorators (e.g.,
`@IsUUID`() and `@IsNotEmpty`() as appropriate) and Swagger decorators (e.g.,
`@ApiProperty`({ type: 'string', format: 'uuid' })) to each of the three fields in
the UpdateIntentDto class to enforce UUID validation and generate proper docs,
and apply the same pattern to ecosystemId and userId in CreateIntentDto to keep
DTO validation consistent with IntentBaseDto’s approach.

In `@apps/ecosystem/repositories/ecosystem.repository.ts`:
- Around line 988-989: The pagination response sets previousPage to pageNumber -
1 which yields 0 when pageNumber === 1; update the logic in the repository
method that builds the pagination object (the fields nextPage and previousPage)
to return null (or clamp to 1) for previousPage when pageNumber <= 1 so
previousPage is never 0; adjust any callers that expect a nullable previousPage
accordingly and keep nextPage as Number(pageNumber) + 1.

In `@apps/ecosystem/src/ecosystem.controller.ts`:
- Around line 260-266: The getIntents method incorrectly uses the HTTP `@Body`()
decorator with a microservice `@MessagePattern`; remove the `@Body`() decorator and
accept the message payload as the plain method parameter (e.g., change signature
of getIntents to async getIntents(payload: any): Promise<object[]>), then
destructure ecosystemId and intentId from payload and call
this.ecosystemService.getIntents(ecosystemId, intentId); ensure you update the
import usage if any and consider replacing the any type with a proper DTO later.

In `@libs/common/src/response-messages/index.ts`:
- Around line 199-200: The messages for the keys fetchIntentTemplates and
fetchVerificationTemplates are inconsistent: update the value for
fetchIntentTemplates to reference "intent template(s)" (e.g., "Ecosystem intent
templates fetched successfully") and remove the leading space in
fetchVerificationTemplates while harmonizing wording/capitalization (e.g.,
"Verification templates fetched successfully") so both messages align with their
keys.

In
`@libs/prisma-service/prisma/migrations/20260119130717_intent_table_creation/migration.sql`:
- Around line 4-11: The migration currently adds ecosystemId to the intents
table as NOT NULL which can break workflows and differs from the
ecosystem_invitations pattern; update the migration to either (A) add
"ecosystemId" as NULLABLE on table "intents" and keep the foreign key constraint
"intents_ecosystemId_fkey" (enforce non-null/uniqueness in application logic),
or (B) convert this to a two-step migration: first ALTER TABLE "intents" ADD
COLUMN "ecosystemId" UUID NULL and add the FK constraint, then in a subsequent
migration backfill existing rows and ALTER TABLE "intents" ALTER COLUMN
"ecosystemId" SET NOT NULL; adjust the migration.sql to use the chosen approach
and ensure constraint name "intents_ecosystemId_fkey" remains correct.
🧹 Nitpick comments (17)
libs/prisma-service/prisma/seed.ts (1)

1-1: Narrow the ESLint disable scope.

File-level camelcase disable can hide new violations; consider // eslint-disable-next-line camelcase on the specific lines instead.

libs/prisma-service/prisma/schema.prisma (1)

706-716: Add an index on intents.ecosystemId to align with codebase patterns.

The codebase consistently indexes FK relationships (e.g., cities.stateId, verification_templates.orgId, intent_templates.intentId). Since intent_templates indexes intentId (the FK to intents), queries on the intents model by ecosystem are likely expected. Postgres doesn't auto-index FK columns, so add an index for performance consistency.

♻️ Proposed change
 model intents {
   id                  String             `@id` `@default`(uuid()) `@db.Uuid`
   ecosystemId         String             `@db.Uuid`
   name                String             `@db.VarChar`(500)
   description         String?
   createDateTime      DateTime           `@default`(now()) `@db.Timestamptz`(6)
   createdBy           String             `@db.Uuid`
   lastChangedDateTime DateTime           `@default`(now()) `@db.Timestamptz`(6)
   lastChangedBy       String             `@db.Uuid`
   ecosystem           ecosystem          `@relation`(fields: [ecosystemId], references: [id])
   intentTemplates     intent_templates[]

+  @@index([ecosystemId])
 }
apps/api-gateway/src/platform/platform.controller.ts (3)

168-183: Redundant validation: route parameter cannot be empty.

The indyNamespace check on line 172 is likely unreachable. NestJS route parameters are required by default, so a request to /platform/network/url/ without a value would result in a 404 (route not found) rather than reaching this handler. The TrimStringParamPipe could trim to empty string, but the validation message implies a missing parameter scenario.

Consider whether you need this check, or if you want to validate against whitespace-only input:

♻️ Suggested refinement
   async getNetwrkUrl(
     `@Param`('indyNamespace', TrimStringParamPipe) indyNamespace: string,
     `@Res`() res: Response
   ): Promise<Response> {
-    if (!indyNamespace) {
-      throw new BadRequestException(ResponseMessages.ledger.error.indyNamespaceisRequired);
-    }
+    // TrimStringParamPipe handles trimming; empty check is defensive
+    if (!indyNamespace?.trim()) {
+      throw new BadRequestException(ResponseMessages.ledger.error.indyNamespaceisRequired);
+    }

239-250: Minor: Inconsistent response construction pattern.

This endpoint constructs the response inline without using the IResponse type, while other endpoints in the same controller use const finalResponse: IResponse = {...}. Consider aligning for consistency.

♻️ Suggested fix
   async createInvitation(
     `@Body`() createEcosystemInvitationDto: CreateEcosystemInvitationDto,
     `@User`() reqUser: user,
     `@Res`() res: Response
   ): Promise<Response> {
     await this.platformService.inviteUserToCreateEcosystem(createEcosystemInvitationDto.email, reqUser.id);
 
-    return res.status(HttpStatus.CREATED).json({
-      statusCode: HttpStatus.CREATED,
-      message: ResponseMessages.ecosystem.success.createInvitation
-    });
+    const finalResponse: IResponse = {
+      statusCode: HttpStatus.CREATED,
+      message: ResponseMessages.ecosystem.success.createInvitation
+    };
+    return res.status(HttpStatus.CREATED).json(finalResponse);
   }

269-277: Minor: Same response pattern inconsistency.

Similar to the createInvitation endpoint, consider using the IResponse type for consistency with other endpoints.

♻️ Suggested fix
   async getInvitations(`@User`() reqUser: user, `@Res`() res: Response): Promise<Response> {
     const invitations = await this.platformService.getInvitationsByUserId(reqUser.id);
 
-    return res.status(HttpStatus.OK).json({
-      statusCode: HttpStatus.OK,
-      message: ResponseMessages.ecosystem.success.fetch,
-      data: invitations
-    });
+    const finalResponse: IResponse = {
+      statusCode: HttpStatus.OK,
+      message: ResponseMessages.ecosystem.success.fetch,
+      data: invitations
+    };
+    return res.status(HttpStatus.OK).json(finalResponse);
   }
apps/api-gateway/src/ecosystem/ecosystem.service.ts (1)

150-154: Unnecessary nesting in payload.

The createIntent method wraps createIntentDto in another object { createIntentDto }. If the receiving handler destructures expecting createIntentDto, this is fine, but verify consistency with the receiver.

apps/ecosystem/src/ecosystem.service.ts (5)

473-488: Inconsistent error handling: Use RpcException for "not found".

Line 477 throws a generic Error for "not found", which will be caught and re-categorized by ErrorHandler.categorize. Other methods in this PR use RpcException directly for similar conditions (e.g., createIntentTemplate at lines 430-433). Consider using RpcException with a proper status code for consistency and clearer error semantics.

♻️ Suggested fix
   async getIntentTemplateById(id: string): Promise<object> {
     try {
       const intentTemplate = await this.ecosystemRepository.getIntentTemplateById(id);
       if (!intentTemplate) {
-        throw new Error('Intent template not found');
+        throw new RpcException({
+          statusCode: HttpStatus.NOT_FOUND,
+          message: 'Intent template not found'
+        });
       }
       return intentTemplate;
     } catch (error) {

593-615: Inconsistent error throwing: BadRequestException vs RpcException.

The createIntent method throws BadRequestException directly (line 598), while other methods in this service use RpcException for validation errors. In a microservice context, RpcException is the preferred exception type as it properly propagates through the message transport.

♻️ Suggested fix
   async createIntent(createIntentDto: CreateIntentDto): Promise<object> {
     try {
       const { name, description, ecosystemId, userId } = createIntentDto;
 
       if (!name || !ecosystemId || !userId) {
-        throw new BadRequestException('name, ecosystemId and userId are required');
+        throw new RpcException({
+          statusCode: HttpStatus.BAD_REQUEST,
+          message: 'name, ecosystemId and userId are required'
+        });
       }

644-669: Same issue: Generic Error thrown for validation.

Line 649 throws a generic Error instead of RpcException. Apply the same fix pattern as above.

♻️ Suggested fix
       if (!intentId || !ecosystemId) {
-        throw new Error('Invalid intentId and ecosystemId are required');
+        throw new RpcException({
+          statusCode: HttpStatus.BAD_REQUEST,
+          message: 'intentId and ecosystemId are required'
+        });
       }

671-683: Same issue: BadRequestException in microservice context.

deleteIntent uses BadRequestException directly. Use RpcException for consistency.

♻️ Suggested fix
   async deleteIntent(ecosystemId: string, intentId: string, user: { id: string }): Promise<object> {
     if (!ecosystemId || !intentId || !user?.id) {
-      throw new BadRequestException('ecosystemId, intentId and user are required');
+      throw new RpcException({
+        statusCode: HttpStatus.BAD_REQUEST,
+        message: 'ecosystemId, intentId and user are required'
+      });
     }

633-639: Missing error handling in getTemplatesByIntentId.

Unlike other methods, getTemplatesByIntentId doesn't have try-catch with ErrorHandler. This could cause unhandled errors to propagate differently than expected.

♻️ Suggested fix
   async getTemplatesByIntentId(orgId: string): Promise<object[]> {
     if (!orgId) {
-      throw new BadRequestException('orgId is required');
+      throw new RpcException({
+        statusCode: HttpStatus.BAD_REQUEST,
+        message: 'orgId is required'
+      });
     }
 
-    return this.ecosystemRepository.getTemplatesByEcosystemId(orgId);
+    try {
+      return await this.ecosystemRepository.getTemplatesByEcosystemId(orgId);
+    } catch (error) {
+      const errorResponse = ErrorHandler.categorize(error, 'Failed to retrieve templates');
+      this.logger.error(
+        `[getTemplatesByIntentId] - ${errorResponse.statusCode}: ${errorResponse.message}`,
+        ErrorHandler.format(error)
+      );
+      throw new RpcException(errorResponse);
+    }
   }
apps/api-gateway/src/ecosystem/ecosystem.controller.ts (3)

724-726: Update intent endpoint missing role-based guard.

Similar to createIntent, this mutation endpoint has no @Roles decorator or role guard. Consider adding authorization to restrict who can update intents.

♻️ Proposed fix
  `@Put`('/intents/:ecosystemId/:intentId')
+ `@Roles`(OrgRoles.OWNER, OrgRoles.ADMIN)
+ `@UseGuards`(AuthGuard('jwt'), OrgRolesGuard)
  `@ApiBearerAuth`()
- `@UseGuards`(AuthGuard('jwt'))
  `@ApiOperation`({

763-765: Delete intent endpoint missing role-based guard.

Delete operations should typically require elevated permissions. Consider adding role-based authorization.

♻️ Proposed fix
  `@Delete`('/intents/:ecosystemId/:intentId')
+ `@Roles`(OrgRoles.OWNER, OrgRoles.ADMIN)
+ `@UseGuards`(AuthGuard('jwt'), OrgRolesGuard)
  `@ApiBearerAuth`()
- `@UseGuards`(AuthGuard('jwt'))
  `@ApiOperation`({

708-708: Method name getTemplateByIntentId is misleading.

The method fetches templates by orgId, not by intentId. Consider renaming for clarity.

apps/ecosystem/repositories/ecosystem.repository.ts (3)

645-660: Missing error handling in createIntentTemplate.

Unlike other repository methods, this lacks try-catch error handling. Prisma errors (e.g., unique constraint violations, FK errors) will propagate unhandled.

♻️ Proposed fix
  async createIntentTemplate(data: {
    orgId?: string;
    intentId: string;
    templateId: string;
    createdBy: string;
  }): Promise<intent_templates> {
+   try {
      return this.prisma.intent_templates.create({
        data: {
          orgId: data.orgId ?? null,
          intentId: data.intentId,
          templateId: data.templateId,
          createdBy: data.createdBy,
          lastChangedBy: data.createdBy
        }
      });
+   } catch (error) {
+     this.logger.error(`Error in createIntentTemplate: ${error}`);
+     throw error;
+   }
  }

1091-1091: Method parameter name is misleading.

The method getTemplatesByEcosystemId takes orgId as parameter, but the name suggests it takes an ecosystem ID. The query logic fetches templates for organizations within an ecosystem.

♻️ Consider renaming for clarity
- async getTemplatesByEcosystemId(orgId: string): Promise<verification_templates[]> {
+ async getTemplatesByOrgEcosystem(orgId: string): Promise<verification_templates[]> {

Or update the implementation to actually accept ecosystemId if that was the intent.


1162-1167: Using deleteMany for a single record deletion.

Since the intent is found by unique id and ecosystemId, using delete would be more appropriate and semantically correct.

♻️ Proposed fix
-   await this.prisma.intents.deleteMany({
-     where: {
-       id: data.intentId,
-       ecosystemId: data.ecosystemId
-     }
-   });
+   await this.prisma.intents.delete({
+     where: { id: data.intentId }
+   });

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🤖 Fix all issues with AI agents
In `@apps/api-gateway/src/platform/platform.controller.ts`:
- Around line 209-219: In getQrCode, stop using process.env directly and inject
Nest's ConfigService to build the URL (use
ConfigService.get('API_GATEWAY_PROTOCOL') and
ConfigService.get('API_ENDPOINT')), wrap the QRCode.toBuffer call in a try/catch
to handle generation errors and respond with a proper error status/log (e.g.,
log the error via this.logger and res.status(500).send()), and if this endpoint
should be protected add the appropriate auth guard or decorator to the getQrCode
route to match the shortening URL's authentication pattern.

In `@apps/api-gateway/src/platform/platform.service.ts`:
- Around line 48-58: Update the incorrect JSDoc for inviteUserToCreateEcosystem
to reflect the actual parameters: replace the `@param`
createEcosystemInvitationDto entry with `@param` email {string} and `@param`
platformAdminId {string}, and adjust the `@returns` description to match the
Promise<IEcosystemInvitations> return type; ensure the JSDoc sits above the
async inviteUserToCreateEcosystem(email: string, platformAdminId: string):
Promise<IEcosystemInvitations> declaration so it documents the function used
with this.natsClient.sendNatsMessage and accurately describes inputs and return
value.

In `@apps/ecosystem/repositories/ecosystem.repository.ts`:
- Around line 943-961: The code uses intentTemplateSearchCriteria.sortField
directly to build orderByField for prisma.intent_templates.findMany which can
throw if the field is invalid; add a validation step that checks
intentTemplateSearchCriteria.sortField against an allowlist of permitted columns
(e.g., ['createDateTime','id','createdBy','intentId','templateId','orgId']) and
only assign orderByField from intentTemplateSearchCriteria.sortField when it
exists in that allowlist, otherwise fallback to the existing default
'createDateTime'; ensure the orderBy usage in the findMany call remains
unchanged and still uses the computed orderByField and orderDirection.
- Around line 560-578: getEcosystemById and getPlatformConfigData currently call
prisma.findFirst() (which may return null) but are typed as non-null; update
each to handle nulls: after awaiting this.prisma.ecosystem.findFirst({ where: {
id } }) in getEcosystemById check if result is null and throw a
NotFoundException (include the id in the message) or alternatively change the
method signature to return Promise<ecosystem | null>; do the same for
getPlatformConfigData (throw a NotFoundException like "Platform config not
found" or return Promise<platform_config | null>), and keep logging the error on
exceptions as currently implemented.
- Around line 582-595: The getIntentTemplateById method currently assumes
prisma.findUnique returns a value and logs success even when it may be null;
update getIntentTemplateById to handle the null case by either changing the
return type to Promise<intent_templates | null> and returning null (and log a
"not found" message) or keep Promise<intent_templates> and throw a NotFoundError
when intentTemplate is null; adjust the logging so this.logger.log(...) is only
called on a successful find and add this.logger.warn(...) or
this.logger.error(...) for the not-found branch; target the
getIntentTemplateById function and the local variable intentTemplate in your
change.
- Around line 693-707: The updateIntentTemplate function currently requires
orgId as a non-null string which prevents updating global templates; change the
parameter signature in updateIntentTemplate to accept orgId?: string | null
(matching createIntentTemplate) and when building the Prisma update payload set
orgId to null when missing (e.g. use data.orgId ?? null) so templates with a
null orgId can be updated; locate the logic in updateIntentTemplate and adjust
the parameter type and the data.orgId assignment accordingly.
- Around line 1091-1104: Rename the method getTemplatesByEcosystemId to
getTemplatesByOrgId to match the orgId parameter and query; update the function
declaration and any internal references (the async function signature and usages
of getTemplatesByEcosystemId) and adjust any exported API or tests that call it.
Locate the prisma query in verification_templates.findMany inside
ecosystem.repository.ts and change the method name, then run a project-wide
search/replace for getTemplatesByEcosystemId → getTemplatesByOrgId to update
callers and exports (keeping the orgId parameter and existing query logic
unchanged).
- Around line 733-762: The getIntentTemplateByIntentAndOrg function queries
intent_templates by intent name and verifierOrgId but does not scope by
ecosystem, so it can return templates from the wrong ecosystem; update the
function signature (getIntentTemplateByIntentAndOrg) to accept an ecosystem
identifier (e.g., ecosystemId), and add an ecosystem filter to the Prisma query
(use organisation.ecosystemId or intent/intent_templates related ecosystem
field) alongside the existing OR on orgId so results are constrained to the
correct ecosystem; ensure the select and orderBy remain unchanged and adjust any
callers to pass the new ecosystemId parameter.

In `@apps/ecosystem/src/ecosystem.service.ts`:
- Around line 473-488: Replace the generic Error throw in getIntentTemplateById
with a NestJS NotFoundException to be explicit: when
ecosystemRepository.getIntentTemplateById(id) returns falsy, throw new
NotFoundException('Intent template not found'); ensure NotFoundException is
imported from `@nestjs/common`; keep the existing catch that uses
ErrorHandler.categorize/format and rethrows RpcException so error logging and
RPC behavior remain unchanged.
- Around line 644-657: In updateIntent (async updateIntent(updateIntentDto:
UpdateIntentDto)), validate that userId exists before calling
ecosystemRepository.updateIntent: check the extracted const { intentId,
ecosystemId, name, description, userId } (or ensure userId is read) and if
missing throw a BadRequestException (not a generic Error) consistent with
createIntent/getTemplatesByIntentId; then call
this.ecosystemRepository.updateIntent with lastChangedBy set to the validated
userId.
♻️ Duplicate comments (9)
libs/prisma-service/prisma/migrations/20260119130717_intent_table_creation/migration.sql (1)

1-11: Consider making ecosystemId nullable or using a two-step migration.

Adding a required column without a default can break non-empty tables; nullable → backfill → NOT NULL is safer.

🛠️ Example (nullable first step)
-ALTER TABLE "intents" ADD COLUMN     "ecosystemId" UUID NOT NULL;
+ALTER TABLE "intents" ADD COLUMN     "ecosystemId" UUID;
libs/common/src/response-messages/index.ts (1)

195-200: Fix message wording for intent templates and verification templates.

🛠️ Suggested fix
-      fetchIntentTemplates: 'Ecosystem intent fetched successfully by id',
-      fetchVerificationTemplates: ' Verification templates fetched successfully'
+      fetchIntentTemplates: 'Ecosystem intent templates fetched successfully',
+      fetchVerificationTemplates: 'Verification templates fetched successfully'
apps/ecosystem/dtos/create-intent.dto.ts (1)

1-7: Add validation & Swagger metadata for ecosystemId and userId.

These fields are required and should match the validation patterns used in other DTOs.

🛠️ Suggested fix
-import { ApiExtraModels } from '@nestjs/swagger';
+import { ApiExtraModels, ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsUUID } from 'class-validator';
 import { IntentBaseDto } from './intent-base.dto';

 `@ApiExtraModels`()
 export class CreateIntentDto extends IntentBaseDto {
-  ecosystemId: string;
-  userId: string;
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  ecosystemId: string;
+
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  userId: string;
 }
#!/bin/bash
# Verify DTO validation patterns used elsewhere for UUID fields
rg -n "@IsUUID" apps/ecosystem/dtos -g "*.ts"
rg -n "CreateIntentDto" -C3 apps/ecosystem
apps/ecosystem/dtos/update-intent.dto.ts (1)

1-8: Add UUID validation & Swagger metadata for ID fields.

intentId, ecosystemId, and userId are unvalidated strings. Align with the existing DTO patterns by adding @ApiProperty({ format: 'uuid' }), @IsUUID(), and @IsNotEmpty() to prevent invalid IDs and keep the Swagger contract accurate.

🔧 Suggested fix
-import { ApiExtraModels } from '@nestjs/swagger';
+import { ApiExtraModels, ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsUUID } from 'class-validator';
 import { IntentBaseDto } from './intent-base.dto';

 `@ApiExtraModels`()
 export class UpdateIntentDto extends IntentBaseDto {
-  intentId: string;
-  ecosystemId: string;
-  userId: string;
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  intentId: string;
+
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  ecosystemId: string;
+
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  userId: string;
 }
apps/api-gateway/src/ecosystem/ecosystem.controller.ts (3)

410-617: Intent-template endpoints need role-based guards.

All intent-template routes are guarded only by AuthGuard('jwt'). If these are meant to be restricted (as other ecosystem routes are), add @Roles(...) and the appropriate roles guard to each handler.


625-628: @Roles on createIntent is not enforced without OrgRolesGuard.

@Roles(OrgRoles.OWNER, OrgRoles.ADMIN) has no effect unless the roles guard is applied.

🔧 Suggested fix
 `@Post`('/intents/:ecosystemId')
 `@Roles`(OrgRoles.OWNER, OrgRoles.ADMIN)
-@UseGuards(AuthGuard('jwt'))
+@UseGuards(AuthGuard('jwt'), OrgRolesGuard)
 `@ApiBearerAuth`()

498-531: Add UUID validation for path params (intentId, orgId, ecosystemId).

Several routes accept UUID path params without ParseUUIDPipe, unlike getIntentTemplateById. Consistent validation prevents invalid IDs from reaching the service layer.

🔧 Example fix (apply similarly to other UUID params)
-async getIntentTemplatesByIntentId(`@Param`('intentId') intentId: string, `@Res`() res: Response): Promise<Response> {
+async getIntentTemplatesByIntentId(
+  `@Param`(
+    'intentId',
+    new ParseUUIDPipe({
+      exceptionFactory: (): Error => {
+        throw new BadRequestException('Invalid intent ID format');
+      }
+    })
+  )
+  intentId: string,
+  `@Res`() res: Response
+): Promise<Response> {

Also applies to: 579-610, 724-777

apps/ecosystem/src/ecosystem.controller.ts (1)

1-1: Don’t use @Body() with @MessagePattern payloads.

In NestJS microservices, the payload is passed directly to the handler. Using @Body() here can yield undefined or malformed payloads.

🔧 Suggested fix
-import { Body, Controller, Logger } from '@nestjs/common';
+import { Controller, Logger } from '@nestjs/common';
...
 `@MessagePattern`({ cmd: 'get-intents' })
-// eslint-disable-next-line `@typescript-eslint/no-explicit-any`
-async getIntents(`@Body`() payload: any): Promise<object[]> {
+async getIntents(payload: { ecosystemId: string; intentId?: string }): Promise<object[]> {
   const { ecosystemId, intentId } = payload;

Also applies to: 260-263

apps/ecosystem/repositories/ecosystem.repository.ts (1)

984-990: previousPage can be 0 on the first page.

When pageNumber === 1, previousPage becomes 0 (Line 988-989), which is not a valid page number.

🧹 Nitpick comments (7)
apps/utility/src/utilities.repository.ts (1)

14-14: Consider adding type annotations for method parameters.

The payload parameter lacks a type annotation. Similarly, referenceId on line 32 is untyped. Adding explicit types improves type safety and IDE support.

💡 Suggested type annotations
-  async saveShorteningUrl(payload): Promise<object> {
+  async saveShorteningUrl(payload: { referenceId: string; invitationPayload: string }): Promise<object> {
-  async getShorteningUrl(referenceId): Promise<shortening_url> {
+  async getShorteningUrl(referenceId: string): Promise<shortening_url> {
apps/api-gateway/src/platform/platform.service.ts (1)

10-10: Cross-module import path may be fragile.

The import uses a relative path reaching into apps/ecosystem/interfaces. This creates a tight coupling between the API gateway and ecosystem modules. Consider exporting shared interfaces from a common library (e.g., @credebl/common/interfaces) for better maintainability.

apps/api-gateway/src/platform/platform.controller.ts (3)

142-151: Return type inconsistency.

The method returns Promise<object> while other similar methods return Promise<Response>. For consistency, update the return type.

♻️ Proposed fix
-  async getAllLedgers(`@Res`() res: Response): Promise<object> {
+  async getAllLedgers(`@Res`() res: Response): Promise<Response> {

168-183: Typo in method name.

The method name getNetwrkUrl is missing the 'o' in 'Network'. Consider renaming to getNetworkUrl for clarity.

♻️ Proposed fix
-  async getNetwrkUrl(
+  async getNetworkUrl(

239-250: Created resource not returned in response.

The inviteUserToCreateEcosystem result is awaited but discarded. Consider returning the created invitation in the response body, which is a common REST pattern for POST endpoints and allows clients to access the created resource's ID without an additional request.

♻️ Proposed fix
   async createInvitation(
     `@Body`() createEcosystemInvitationDto: CreateEcosystemInvitationDto,
     `@User`() reqUser: user,
     `@Res`() res: Response
   ): Promise<Response> {
-    await this.platformService.inviteUserToCreateEcosystem(createEcosystemInvitationDto.email, reqUser.id);
+    const invitation = await this.platformService.inviteUserToCreateEcosystem(createEcosystemInvitationDto.email, reqUser.id);

     return res.status(HttpStatus.CREATED).json({
       statusCode: HttpStatus.CREATED,
-      message: ResponseMessages.ecosystem.success.createInvitation
+      message: ResponseMessages.ecosystem.success.createInvitation,
+      data: invitation
     });
   }
libs/prisma-service/prisma/schema.prisma (1)

706-716: Consider indexing intents.ecosystemId for query performance.

Most intent queries will likely filter by ecosystem; an index will help.

🛠️ Suggested change
 model intents {
   id                  String             `@id` `@default`(uuid()) `@db.Uuid`
   ecosystemId         String             `@db.Uuid`
   name                String             `@db.VarChar`(500)
   description         String?
   createDateTime      DateTime           `@default`(now()) `@db.Timestamptz`(6)
   createdBy           String             `@db.Uuid`
   lastChangedDateTime DateTime           `@default`(now()) `@db.Timestamptz`(6)
   lastChangedBy       String             `@db.Uuid`
   ecosystem           ecosystem          `@relation`(fields: [ecosystemId], references: [id])
   intentTemplates     intent_templates[]
+
+  @@index([ecosystemId])
 }
apps/ecosystem/src/ecosystem.service.ts (1)

633-639: Rename getTemplatesByIntentId to reflect the orgId parameter.

The method name suggests an intentId lookup, but it accepts orgId and calls getTemplatesByEcosystemId. Renaming to something like getTemplatesByOrgId (or adjusting the parameter) would reduce confusion.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@apps/api-gateway/src/ecosystem/ecosystem.controller.ts`:
- Around line 658-679: The getIntents method is missing UUID validation for the
ecosystemId parameter; update the `@Param` decorator to use ParseUUIDPipe (as used
elsewhere) so the signature becomes `@Param`('ecosystemId', new ParseUUIDPipe())
ecosystemId: string and ensure ParseUUIDPipe is imported from `@nestjs/common`;
this enforces UUID format consistency for the getIntents handler.

In `@apps/api-gateway/src/ecosystem/ecosystem.service.ts`:
- Around line 113-133: The payloads sent from createIntentTemplate and
updateIntentTemplate (and the other method at lines ~202–203) forward the
IUserRequest object directly but the ecosystem service expects user.id, not
user.userId; update those methods (createIntentTemplate, updateIntentTemplate
and the other senders of `user: IUserRequest`) to normalize the user field by
mapping user.userId → id (e.g., build payload.user = { ...user, id: user.userId
} or set id explicitly) before calling this.natsClient.sendNatsMessage so the
downstream checks for user.id succeed.

In `@apps/api-gateway/src/platform/platform.controller.ts`:
- Around line 58-62: The Swagger query param name in the platform controller is
mismatched with the DTO: change the ApiQuery decorator on the get-all endpoint
to use the DTO's field name "sorting" (instead of "sortField") so Swagger docs
and NestJS binding align with GetAllSchemaByPlatformDto; update the ApiQuery
name property that currently references SortFields to "sorting" (or
alternatively rename the DTO field to match the existing "sortField") and ensure
enum remains SortFields so clients and the controller receive the value
correctly.

In `@apps/ecosystem/src/ecosystem.service.ts`:
- Around line 555-565: The updateIntentTemplate method dereferences user.id
without validation; add the same guard used in createIntentTemplate: verify that
data.user and data.user.id exist and are non-empty, and if not throw new
RpcException({ code: HttpStatus.BAD_REQUEST, message: 'user.id is required' })
(or the exact message pattern used in createIntentTemplate) before calling
this.ecosystemRepository.updateIntentTemplate, ensuring lastChangedBy is only
set from a validated user.id.
♻️ Duplicate comments (15)
apps/api-gateway/src/platform/platform.service.ts (1)

48-53: JSDoc doesn’t match the method signature.

The comment still references createEcosystemInvitationDto and a generic success return, but the method accepts (email, platformAdminId) and returns IEcosystemInvitations. Please align the JSDoc with the actual parameters/return type.

📝 Suggested JSDoc update
-  /**
-   *
-   * `@param` createEcosystemInvitationDto
-   * `@returns` Ecosystem creation success
-   */
+  /**
+   * Invites a user to create an ecosystem
+   * `@param` email - The email address of the user to invite
+   * `@param` platformAdminId - The platform admin ID issuing the invitation
+   * `@returns` The created invitation record
+   */
apps/api-gateway/src/platform/platform.controller.ts (1)

202-219: Add error handling + avoid direct env access (already flagged).

QRCode.toBuffer() can throw, and direct process.env access bypasses config validation/typing. Consider try/catch + ConfigService.

Is QRCode.toBuffer documented to throw/reject on invalid input or generation failure in the qrcode npm package?
apps/ecosystem/repositories/ecosystem.repository.ts (6)

1091-1115: Rename getTemplatesByEcosystemId to match the orgId parameter.

The method name suggests ecosystem filtering, but it actually filters by org membership.


560-579: Handle null results from findFirst.

Line 562 and Line 574 can return null, but the methods are typed as non‑null. Either throw NotFoundException or return nullable types.

🐛 Proposed guard
 async getEcosystemById(id: string): Promise<ecosystem> {
   try {
     const result = await this.prisma.ecosystem.findFirst({
       where: { id }
     });
+    if (!result) {
+      throw new NotFoundException('Ecosystem not found');
+    }
     return result;
   } catch (error) {
     this.logger.error(`Error in getEcosystemById: ${error.message}`);
     throw error;
   }
 }

 async getPlatformConfigData(): Promise<platform_config> {
   try {
-    return await this.prisma.platform_config.findFirst();
+    const config = await this.prisma.platform_config.findFirst();
+    if (!config) {
+      throw new NotFoundException('Platform config not found');
+    }
+    return config;
   } catch (error) {
     this.logger.error(`Error in getPlatformConfigData: ${error.message}`);
     throw error;
   }
 }

582-595: Guard against missing intent templates.

Line 584 can return null, but the method returns Promise<intent_templates> and logs success even when not found.

🐛 Proposed guard
 const intentTemplate = await this.prisma.intent_templates.findUnique({
   where: { id },
   include: {
     organisation: true,
     intent: true,
     template: true
   }
 });

+if (!intentTemplate) {
+  throw new NotFoundException('Intent template not found');
+}
 this.logger.log(`[getIntentTemplateById] - Intent template details ${id}`);
 return intentTemplate;

693-707: Allow orgId to be nullable on update.

Line 695 requires orgId, but createIntentTemplate allows null, so global templates can’t be updated.

♻️ Suggested fix
-  async updateIntentTemplate(
-    id: string,
-    data: { orgId: string; intentId: string; templateId: string; lastChangedBy: string }
-  ): Promise<intent_templates> {
+  async updateIntentTemplate(
+    id: string,
+    data: { orgId?: string | null; intentId: string; templateId: string; lastChangedBy: string }
+  ): Promise<intent_templates> {
...
-          orgId: data.orgId,
+          orgId: data.orgId ?? null,

733-762: Scope intent-template lookup by ecosystem.

Line 737 filters by intent name and org only. If an org belongs to multiple ecosystems, this can return a template from the wrong ecosystem. Add ecosystemId to the filter and method signature.

🐛 Suggested fix (signature + filter)
-async getIntentTemplateByIntentAndOrg(intentName: string, verifierOrgId: string)
+async getIntentTemplateByIntentAndOrg(intentName: string, verifierOrgId: string, ecosystemId: string)
...
-  intent: { is: { name: intentName } },
+  intent: { is: { name: intentName, ecosystemId } },

907-992: Harden sort field and pagination metadata.

Line 943 uses a client‑provided sortField directly (invalid fields will throw). Line 989 can return previousPage = 0. Add an allowlist and clamp.

♻️ Suggested fix
-const orderByField = intentTemplateSearchCriteria.sortField || 'createDateTime';
+const allowedSortFields = new Set(['createDateTime', 'intentId', 'templateId', 'orgId', 'id']);
+const requestedSortField = intentTemplateSearchCriteria.sortField || 'createDateTime';
+const orderByField = allowedSortFields.has(requestedSortField) ? requestedSortField : 'createDateTime';
 ...
-previousPage: pageNumber - 1,
+previousPage: hasPreviousPage ? pageNumber - 1 : 1,
libs/prisma-service/prisma/migrations/20260119130717_intent_table_creation/migration.sql (1)

1-11: Avoid adding a NOT NULL column without backfill.

Line 8 adds ecosystemId as NOT NULL, which will fail if intents is non‑empty. Consider a two‑step migration (add nullable → backfill → set NOT NULL) or make it nullable if the workflow allows it.

🛠️ Safer migration approach (step 1)
-ALTER TABLE "intents" ADD COLUMN     "ecosystemId" UUID NOT NULL;
+ALTER TABLE "intents" ADD COLUMN     "ecosystemId" UUID;
libs/common/src/response-messages/index.ts (1)

194-200: Fix intent-template success message text.

Line 199 refers to a single intent rather than intent templates, and Line 200 has a leading space.

🛠️ Suggested fix
-      fetchIntentTemplates: 'Ecosystem intent fetched successfully by id',
-      fetchVerificationTemplates: ' Verification templates fetched successfully'
+      fetchIntentTemplates: 'Ecosystem intent templates fetched successfully',
+      fetchVerificationTemplates: 'Verification templates fetched successfully'
apps/ecosystem/dtos/create-intent.dto.ts (1)

1-7: Add validation and Swagger metadata for ID fields.

Line 6–7 lacks UUID validation and Swagger docs, which makes API contracts weaker.

✅ Suggested fix
-import { ApiExtraModels } from '@nestjs/swagger';
+import { ApiExtraModels, ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsUUID } from 'class-validator';
 import { IntentBaseDto } from './intent-base.dto';

 `@ApiExtraModels`()
 export class CreateIntentDto extends IntentBaseDto {
-  ecosystemId: string;
-  userId: string;
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  ecosystemId: string;
+
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  userId: string;
 }
apps/ecosystem/dtos/update-intent.dto.ts (1)

1-8: Add validation and Swagger metadata for ID fields.

Line 6–8 are required identifiers but aren’t validated or documented.

✅ Suggested fix
-import { ApiExtraModels } from '@nestjs/swagger';
+import { ApiExtraModels, ApiProperty } from '@nestjs/swagger';
+import { IsNotEmpty, IsUUID } from 'class-validator';
 import { IntentBaseDto } from './intent-base.dto';

 `@ApiExtraModels`()
 export class UpdateIntentDto extends IntentBaseDto {
-  intentId: string;
-  ecosystemId: string;
-  userId: string;
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  intentId: string;
+
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  ecosystemId: string;
+
+  `@ApiProperty`({ format: 'uuid' })
+  `@IsUUID`()
+  `@IsNotEmpty`()
+  userId: string;
 }
apps/api-gateway/src/ecosystem/ecosystem.controller.ts (2)

410-618: Add role-based guards for intent-template CRUD endpoints.
Lines 410–618 only apply AuthGuard('jwt'), so any authenticated user can create/update/delete intent templates. Add @Roles(...) + the appropriate roles guard (OrgRolesGuard/EcosystemRolesGuard) or move the guard to the controller level.


625-628: @Roles is not enforced without OrgRolesGuard.
Line 627 applies @Roles(...) but the guard stack only includes AuthGuard('jwt'), so role checks won’t run.

🔒 Suggested fix
  `@Post`('/intents/:ecosystemId')
  `@Roles`(OrgRoles.OWNER, OrgRoles.ADMIN)
- `@UseGuards`(AuthGuard('jwt'))
+ `@UseGuards`(AuthGuard('jwt'), OrgRolesGuard)
  `@ApiBearerAuth`()
apps/ecosystem/src/ecosystem.controller.ts (1)

260-265: Remove @Body() from the @MessagePattern handler.
Line 262 uses an HTTP decorator inside a microservice handler, which can result in payload being undefined. Accept the payload directly.

🔧 Suggested fix
  `@MessagePattern`({ cmd: 'get-intents' })
  // eslint-disable-next-line `@typescript-eslint/no-explicit-any`
- async getIntents(`@Body`() payload: any): Promise<object[]> {
+ async getIntents(payload: any): Promise<object[]> {
    const { ecosystemId, intentId } = payload;

    return this.ecosystemService.getIntents(ecosystemId, intentId);
  }
🧹 Nitpick comments (2)
apps/api-gateway/src/platform/platform.controller.ts (1)

239-242: Use the auth user interface instead of Prisma user for request context.

@User() typically yields an auth-context object (e.g., IUserRequestInterface), not a Prisma entity. Typing it as user reduces type safety and can mislead about available fields.

♻️ Suggested type alignment
-  async createInvitation(
-    `@Body`() createEcosystemInvitationDto: CreateEcosystemInvitationDto,
-    `@User`() reqUser: user,
+  async createInvitation(
+    `@Body`() createEcosystemInvitationDto: CreateEcosystemInvitationDto,
+    `@User`() reqUser: IUserRequestInterface,
     `@Res`() res: Response
   ): Promise<Response> {
-  async getInvitations(`@User`() reqUser: user, `@Res`() res: Response): Promise<Response> {
+  async getInvitations(`@User`() reqUser: IUserRequestInterface, `@Res`() res: Response): Promise<Response> {

Also applies to: 269-270

libs/prisma-service/prisma/schema.prisma (1)

706-717: Add an index on intents.ecosystemId for frequent lookups.

Line 708 introduces ecosystemId, and repository queries filter by this field. Add an index to avoid sequential scans as the table grows.

♻️ Proposed Prisma schema change
 model intents {
   id                  String             `@id` `@default`(uuid()) `@db.Uuid`
   ecosystemId         String             `@db.Uuid`
   name                String             `@db.VarChar`(500)
   description         String?
   createDateTime      DateTime           `@default`(now()) `@db.Timestamptz`(6)
   createdBy           String             `@db.Uuid`
   lastChangedDateTime DateTime           `@default`(now()) `@db.Timestamptz`(6)
   lastChangedBy       String             `@db.Uuid`
   ecosystem           ecosystem          `@relation`(fields: [ecosystemId], references: [id])
   intentTemplates     intent_templates[]
+
+  @@index([ecosystemId])
 }

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
@sonarqubecloud
Copy link

@pranalidhanavade pranalidhanavade merged commit 7863c23 into feat/platform_admin_and_ecosystem Jan 27, 2026
5 checks passed
pranalidhanavade added a commit that referenced this pull request Jan 30, 2026
…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>
pranalidhanavade added a commit that referenced this pull request Jan 30, 2026
…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>
pranalidhanavade added a commit that referenced this pull request Jan 31, 2026
* 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>
shitrerohit pushed a commit that referenced this pull request Jan 31, 2026
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants