Skip to content

feat: platform admin and ecosystem#1551

Merged
pranalidhanavade merged 12 commits intomainfrom
feat/platform_admin_and_ecosystem
Jan 31, 2026
Merged

feat: platform admin and ecosystem#1551
pranalidhanavade merged 12 commits intomainfrom
feat/platform_admin_and_ecosystem

Conversation

@pranalidhanavade
Copy link
Contributor

@pranalidhanavade pranalidhanavade commented Jan 30, 2026

What

  • Added ecosystem service and created ecosystem invitation API routes.
  • Added a script to add platform admins to Keycloak and create user organization roles.
  • Added ecosystem member invitation and management APIs.
  • Fixed the versioning for nest-cli.
  • Added a Dockerfile for the ecosystem service.
  • Added the ecosystem service to the GitHub Actions workflow.
  • Added intent API endpoints and intent template mapping APIs.
  • Fixed issues regarding the Docker build process.
  • Fixed and enabled the functionality to toggle ecosystem status.

Summary by CodeRabbit

  • New Features

    • Ecosystem product: new microservice and gateway APIs to create/manage ecosystems, orgs, memberships, dashboards, intents and templates.
    • Invitation flows: invite users to create or join ecosystems with branded email templates and dashboard metrics.
    • Platform admin UI: enable/disable ecosystem feature and manage platform-level invites.
  • Permissions

    • New roles: Ecosystem Lead and Ecosystem Member with role-based guards.
  • Chores

    • New env/config keys and DB migrations to support ecosystem deployment and feature flag.

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

pranalidhanavade and others added 9 commits January 12, 2026 11:51
)

* 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>
…g 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/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>
Signed-off-by: sujitaw <sujit.sutar@ayanworks.com>
Signed-off-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com>
Signed-off-by: sahil.kamble@ayanworks.com <sahil.kamble@ayanworks.com>
…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>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
* 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>
@pranalidhanavade pranalidhanavade self-assigned this Jan 30, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 30, 2026

📝 Walkthrough

Walkthrough

Adds a new NATS-backed "ecosystem" microservice and integrates it across the monorepo: DB schema/migrations and seed updates, gateway wiring (modules/guards/JWT/swagger), DTOs/controllers/services/repositories, email templates, CI/Docker/tsconfig, enums/constants, and moves intent-template surface to the ecosystem domain. (50 words)

Changes

Cohort / File(s) Summary
Config & CI
\.env.sample, .github/workflows/continuous-delivery.yml, pnpm-workspace.yaml, nest-cli.json
New ECOSYSTEM_NKEY_SEED and platform-admin Keycloak vars added to sample; ecosystem added to CI matrix and nest projects; dependency pin in workspace.
Docker & Build
Dockerfiles/Dockerfile.ecosystem, apps/ecosystem/tsconfig.app.json
New multi-stage Dockerfile and tsconfig for ecosystem app.
Ecosystem Microservice Bootstrap
apps/ecosystem/src/main.ts
New Nest microservice bootstrap using NATS and ECOSYSTEM_NKEY_SEED.
API Gateway Integration
apps/api-gateway/src/app.module.ts, apps/api-gateway/src/main.ts, apps/api-gateway/src/authz/..., apps/api-gateway/src/ecosystem/...
Wired EcosystemModule into gateway; added EcosystemSwaggerFilter, EcosystemFeatureGuard, EcosystemRolesGuard, JWT enrichment, ecosystem controller/service/module for gateway-facing endpoints.
Ecosystem Domain (app)
apps/ecosystem/src/ecosystem.service.ts, apps/ecosystem/src/ecosystem.controller.ts, apps/ecosystem/repositories/ecosystem.repository.ts, apps/ecosystem/src/ecosystem.module.ts
New repository, service, controller, module, and NATS handlers implementing ecosystem lifecycle, invitations, orgs, intents and templates.
DTOs, Interfaces & Templates
apps/ecosystem/dtos/*, apps/ecosystem/interfaces/*, apps/ecosystem/templates/*
Many DTOs, interfaces and HTML email templates added for invites, intents and templates.
Prisma Schema / Migrations / Seed
libs/prisma-service/prisma/schema.prisma, .../migrations/*, libs/prisma-service/prisma/seed.ts, libs/prisma-service/prisma/data/*
New ecosystem models/tables, intents.ecosystemId, platform_config.isEcosystemEnabled, migration SQL and seed enhancements (Keycloak helpers, client-id migration, ecosystem roles/config seeding).
Enums, Constants & Messages
libs/enum/src/enum.ts, libs/org-roles/enums/index.ts, libs/common/src/common.constant.ts, libs/common/src/response-messages/index.ts
Added ecosystem enums/roles, ECOSYSTEM_SERVICE constant and ResponseMessages.ecosystem entries.
Intent Template Migration
apps/api-gateway/src/utilities/*, apps/utility/src/*
Intent-template CRUD removed from utilities and moved into ecosystem app (handlers, service/repo logic removed from utilities).
Module Exports & Cross-module Wiring
apps/organization/src/organization.module.ts, apps/user/src/user.module.ts, apps/api-gateway/src/platform/*
Exported repositories and added EcosystemServiceModule wiring; platform controller/service extended for invitation and ecosystem config endpoints.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant API as "API Gateway"
    participant JWT as "JwtStrategy"
    participant GatewaySvc as "Gateway EcosystemService"
    participant NATS as "NATS Bus"
    participant EcoMS as "Ecosystem Microservice"
    participant DB as "Database"

    Client->>API: Request with JWT
    API->>JWT: Validate token
    JWT->>GatewaySvc: fetch ecosystem roles (getUserByKeycloakId)
    GatewaySvc->>NATS: publish request (get-user-by-keycloak-id)
    NATS->>EcoMS: route to ecosystem handler
    EcoMS->>DB: query user/ecosystem data
    DB-->>EcoMS: return data
    EcoMS-->>NATS: respond
    NATS-->>GatewaySvc: deliver roles/data
    GatewaySvc-->>JWT: return ecosystem roles
    API->>Client: Response (enriched user context)
Loading
sequenceDiagram
    autonumber
    participant Admin
    participant PlatformCtrl as "PlatformController"
    participant PlatformSvc as "PlatformService"
    participant NATS as "NATS Bus"
    participant EcoMS as "Ecosystem Microservice"
    participant Repo as "EcosystemRepository"
    participant DB as "Database"
    participant Email as "EmailService"

    Admin->>PlatformCtrl: POST /invitations (email)
    PlatformCtrl->>PlatformSvc: inviteUserToCreateEcosystem(email)
    PlatformSvc->>NATS: publish invite-user-for-ecosystem
    NATS->>EcoMS: invoke invitation handler
    EcoMS->>Repo: createEcosystemInvitation(...)
    Repo->>DB: insert invitation
    Repo-->>EcoMS: invitation record
    EcoMS->>Email: send invite email
    Email-->>EcoMS: queued
    EcoMS-->>NATS: return IEcosystemInvitations
    NATS-->>PlatformSvc: deliver response
    PlatformSvc-->>PlatformCtrl: return created invitation
    PlatformCtrl-->>Admin: 201 Created + payload
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested labels

feature

Suggested reviewers

  • shitrerohit
  • RinkalBhojani

"A rabbit hops in code and cheer, 🐇
I stitched invites and bridges clear,
NATS seeds whisper, services wake,
Guards stand watch for every stake,
Hop—ecosystems bloom and steer."

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: platform admin and ecosystem' clearly references the main additions in this changeset: platform admin configuration and ecosystem service infrastructure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/platform_admin_and_ecosystem

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.

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

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/utility/src/utilities.service.ts (1)

83-109: ⚠️ Potential issue | 🟡 Minor

Set isSendingAlert before the async config fetch to make the single-flight guard effective.
Because the flag is set after await getPlatformConfigDetails, concurrent calls can both pass the guard and trigger parallel retry flows.

Proposed fix
   async handleLedgerAlert(emailDto: EmailDto): Promise<void> {
     const now = Date.now();
@@
     if (this.isSendingAlert) {
       this.logger.log('Alert email sending already in progress, skipping...');
       return;
     }
 
-    const platformConfigData = await this.utilitiesRepository.getPlatformConfigDetails();
-    if (!platformConfigData) {
-      throw new NotFoundException(ResponseMessages.issuance.error.platformConfigNotFound);
-    }
-
-    emailDto.emailFrom = platformConfigData?.emailFrom;
-
-    // 3. Start async retry flow — do not block the caller
-    this.isSendingAlert = true;
-    this.sendWithRetry(emailDto).finally(() => {
-      this.isSendingAlert = false;
-    });
+    this.isSendingAlert = true;
+    try {
+      const platformConfigData = await this.utilitiesRepository.getPlatformConfigDetails();
+      if (!platformConfigData) {
+        throw new NotFoundException(ResponseMessages.issuance.error.platformConfigNotFound);
+      }
+      emailDto.emailFrom = platformConfigData?.emailFrom;
+
+      // 3. Start async retry flow — do not block the caller
+      this.sendWithRetry(emailDto).finally(() => {
+        this.isSendingAlert = false;
+      });
+    } catch (err) {
+      this.isSendingAlert = false;
+      throw err;
+    }
   }
libs/prisma-service/prisma/seed.ts (1)

245-256: ⚠️ Potential issue | 🔴 Critical

Logic bug: Condition always prevents record creation.

The condition if (!userId && !orgId && !orgRoleId) at line 245 only executes the create block when ALL three are falsy/null. However, if any of them is null (e.g., user not found), you'd want to skip creation. The current logic means records are only created when the lookups fail, but then lines 248-250 would throw errors trying to access .id on null values.

This appears to be inverted logic. Consider:

🐛 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('Skipping user_org_roles: required entities not found');
     }
🤖 Fix all issues with AI agents
In `@apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts`:
- Around line 37-49: UpdateEcosystemInvitationDto currently requires ecosystemId
which blocks deferred-ecosystem flows; make the property optional and allow null
by adding `@IsOptional`() and changing the TypeScript type to optional/nullable
(e.g., ecosystemId?: string | null), remove the `@IsNotEmpty`() decorator from the
ecosystemId field, keep `@IsUUID`()/@IsString() and the `@Transform`(trim) so
validations only run when a value is provided; target the
UpdateEcosystemInvitationDto -> ecosystemId property and adjust decorators/type
accordingly.

In `@apps/api-gateway/src/ecosystem/ecosystem.service.ts`:
- Around line 72-74: The deleteEcosystemOrgs method sends a payload key userIds
but the microservice handler expects orgIds, causing a mismatch; update the
payload in this.natsClient.sendNatsMessage call inside deleteEcosystemOrgs to
send { orgIds: userIds, ecosystemId } (or rename the method parameter to orgIds
and send { orgIds, ecosystemId }) so the key matches the handler for the
'delete-ecosystem-orgs' message in ecosystem.controller.

In `@apps/ecosystem/repositories/ecosystem.repository.ts`:
- Around line 119-171: The code in createNewEcosystem creates the ecosystem
before validating ecosystemRoleDetails, which can leave an orphaned ecosystem if
the role is missing; move the prisma.ecosystem_roles.findFirst() check and the
null check for ecosystemRoleDetails to before calling prisma.ecosystem.create
(and throw NotFoundException there), or perform both operations inside a single
atomic Prisma transaction so the create is rolled back if the role is absent;
reference ecosystemRoleDetails, prisma.ecosystem_roles.findFirst,
prisma.ecosystem.create, and the NotFoundException when making the change.

In `@apps/ecosystem/src/ecosystem.controller.ts`:
- Around line 239-242: The message handler deleteIntentTemplate currently
expects a bare string id but the gateway sends an object { id }; update the
handler signature to accept the payload object (e.g.,
deleteIntentTemplate(payload: { id: string }) or destructure
deleteIntentTemplate({ id }: { id: string })) and call
this.ecosystemService.deleteIntentTemplate(id) so the correct id is forwarded to
the service.
- Around line 193-206: The MessagePattern handlers getIntentTemplateById,
getIntentTemplatesByIntentId, and getIntentTemplatesByOrgId currently declare
primitive parameters but the gateway sends wrapped objects; update each handler
signature to accept the payload object (e.g., payload: { id: string } for
getIntentTemplateById, payload: { intentId: string } for
getIntentTemplatesByIntentId, payload: { orgId: string } for
getIntentTemplatesByOrgId), extract the id (const { id } = payload etc.) and
pass that extracted string to the corresponding ecosystemService methods
(ecosystemService.getIntentTemplateById, .getIntentTemplatesByIntentId,
.getIntentTemplatesByOrgId).

In `@apps/ecosystem/templates/invite-member-template.ts`:
- Around line 7-48: The template directly injects process.env values and lacks
validation/escaping; add a small pre-template step (similar to
CreateEcosystemInviteTemplate) that verifies required env vars (BRAND_LOGO,
PLATFORM_NAME, PUBLIC_PLATFORM_SUPPORT_EMAIL, POWERED_BY) are present and
throws/returns a clear error if missing, then HTML-escape each value (e.g.,
escapeBrandLogo, escapePlatformName, escapeSupportEmail, escapePoweredBy) and
use those escaped variables inside the returned string instead of process.env.*
to prevent runtime errors and injection.
- Around line 4-6: The template inserts ecosystemName into HTML without
escaping, creating an XSS risk; update sendInviteEmailTemplate to
sanitize/escape ecosystemName (e.g., pass ecosystemName through the existing
escapeHtml function or another trusted sanitizer) before embedding it in the
returned HTML string so all user-controlled values are escaped like the
safeEmail usage.

In `@Dockerfiles/Dockerfile.ecosystem`:
- Line 44: The Docker CMD currently runs migrations ("prisma migrate deploy") at
container start which risks concurrent runs in multi-replica deployments; remove
the migration step from the CMD in Dockerfile.ecosystem (the CMD that executes
"cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate &&
...") and instead run migrations outside the app container (e.g., as a separate
init container or Kubernetes Job, a CI/CD step before rollout, or via a
dedicated migration service/lock mechanism) so only one process performs "prisma
migrate deploy" while the app startup keeps only the generate and node start
steps.
- Around line 10-17: The Dockerfile runs `RUN pnpm i --ignore-scripts` without
copying the pnpm lockfile, making builds non-reproducible; update the Dockerfile
so it copies `pnpm-lock.yaml` into the image prior to running `pnpm i` (i.e.,
add a `COPY pnpm-lock.yaml ./` step before the `RUN pnpm i --ignore-scripts`
line), ensuring `package.json`, `pnpm-workspace.yaml`, and the lockfile are
present for deterministic installs.

In
`@libs/prisma-service/prisma/data/credebl-master-table/credebl-master-table.json`:
- Line 29: Replace the hardcoded "Admin@123" value for the JSON key
platformAdminKeycloakPassword with an empty string placeholder, and update the
seeding logic that consumes this field (the seed function that loads
credebl-master-table data) to read the real password from an environment
variable named PLATFORM_ADMIN_KEYCLOAK_PASSWORD at runtime instead of relying on
the JSON value; ensure the seed code falls back to an error or skip if the env
var is missing.

In `@libs/prisma-service/prisma/seed.ts`:
- Around line 141-167: The code in createEcosystemRoles reads ecosystemRoleData
from JSON parsed from configData but that key is missing in
credebl-master-table.json, causing ecosystemRoleData to be undefined and
ecosystemRoleData.map() to throw; fix by validating the parsed value before use:
after parsing configData (in createEcosystemRoles) check that ecosystemRoleData
is an array (e.g., typeof/Array.isArray check) and if missing either default to
an empty array or log and return early to avoid calling .map, and update the
error/log messages around prisma.ecosystem_roles.createMany to reflect the
conditional behavior so seeding only runs when valid data exists.
🟡 Minor comments (20)
pnpm-workspace.yaml-22-22 (1)

22-22: ⚠️ Potential issue | 🟡 Minor

Make @nestjs/cli version specifier consistent with other @nestjs dependencies.

@nestjs/cli is pinned to exact version 11.0.10, while all other @nestjs packages in the catalog use caret (^) for patch flexibility. This inconsistency causes the CLI to miss patch updates; the latest version is 11.0.14.

Change @nestjs/cli to ^11.0.10 to match the dependency pattern and receive security/patch updates automatically.

libs/org-roles/enums/index.ts-1-12 (1)

1-12: ⚠️ Potential issue | 🟡 Minor

Inconsistent naming convention for ecosystem role values.

Existing roles use snake_case values (e.g., 'owner', 'super_admin'), but the new ecosystem roles use Title Case (e.g., 'Ecosystem Lead'). This inconsistency appears throughout the codebase:

  • Defined in both OrgRoles and EcosystemRoles enums
  • Stored in constants (ECOSYSTEM_ROLES in common.constant.ts)
  • Used in database queries and seed data

While the Title Case format is the current database value (not just display), this violates the established naming pattern and could cause confusion for developers working with role strings.

Align ecosystem roles with the existing snake_case convention by changing:

  • 'Ecosystem Lead''ecosystem_lead'
  • 'Ecosystem Member''ecosystem_member'

Note: This will require a database migration to update existing role records.

apps/ecosystem/templates/create-ecosystem.templates.ts-13-20 (1)

13-20: ⚠️ Potential issue | 🟡 Minor

Environment variables are escaped before validation check.

escapeHtml() is called on process.env.BRAND_LOGO, etc. (lines 13-16) before checking if they exist (lines 17-20). If any env var is undefined, escapeHtml(undefined) will throw an error or produce unexpected results, bypassing your helpful error message.

🔧 Proposed fix to reorder validation
   public sendInviteEmailTemplate(isUserExist: boolean): string {
     const requiredEnvVars = [
       'FRONT_END_URL',
       'PLATFORM_NAME',
       'BRAND_LOGO',
       'PUBLIC_PLATFORM_SUPPORT_EMAIL',
       'POWERED_BY'
     ];

+    const missingVars = requiredEnvVars.filter((varName) => !process.env[varName]);
+    if (missingVars.length > 0) {
+      throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`);
+    }
+
     const brandLogo = escapeHtml(process.env.BRAND_LOGO);
     const platformName = escapeHtml(process.env.PLATFORM_NAME);
     const supportEmail = escapeHtml(process.env.PUBLIC_PLATFORM_SUPPORT_EMAIL);
     const poweredBy = escapeHtml(process.env.POWERED_BY);
-    const missingVars = requiredEnvVars.filter((varName) => !process.env[varName]);
-    if (0 < missingVars.length) {
-      throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`);
-    }
apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts-52-58 (1)

52-58: ⚠️ Potential issue | 🟡 Minor

Fix the find() callback to always return a boolean.
Current callback has no explicit return on the non-match path, and a lint error is already reported. .some() is cleaner here.

✅ Suggested fix
-      // eslint-disable-next-line array-callback-return
-      const isPlatformAdminFlag = user.userOrgRoles.find((orgDetails) => {
-        if (orgDetails.orgRole.name === OrgRoles.PLATFORM_ADMIN) {
-          return true;
-        }
-      });
+      const isPlatformAdminFlag = user.userOrgRoles.some(
+        (orgDetails) => orgDetails.orgRole.name === OrgRoles.PLATFORM_ADMIN
+      );
apps/api-gateway/src/authz/jwt.strategy.ts-124-129 (1)

124-129: ⚠️ Potential issue | 🟡 Minor

Resolve the array-bracket-newline lint error in ecosystem role list.
The current formatting violates the lint rule; tightening the brackets fixes it without changing logic.

🧹 Suggested formatting fix
-      const ecosystemRoleList = [
-        ...new Set(ecosystemRole.map((record: { ecosystemRole: { name: string } }) => record.ecosystemRole.name))
-      ];
+      const ecosystemRoleList = [...new Set(
+        ecosystemRole.map((record: { ecosystemRole: { name: string } }) => record.ecosystemRole.name)
+      )];
libs/common/src/response-messages/index.ts-163-287 (1)

163-287: ⚠️ Potential issue | 🟡 Minor

Fix user-facing typos/misleading wording in ecosystem messages.
A few error strings are misleading or grammatically incorrect, which can confuse clients and support.

📝 Suggested message-only corrections
-      updatedEcosytemOrg: 'Updated ecosytem org successfully',
+      updatedEcosytemOrg: 'Updated ecosystem org successfully',

-      signTransactionNotApplicable: 'Signing transaction for w3c schema is not aapllicable',
+      signTransactionNotApplicable: 'Signing transaction for w3c schema is not applicable',

-      credentialDefinitionNotFound: 'Credential definition found',
+      credentialDefinitionNotFound: 'Credential definition not found',

-      invalidFormatOfIntentId: 'Invalid format of ecosystemId',
+      invalidFormatOfIntentId: 'Invalid format of intentId',

-      noRecordsFound: 'No records not found',
+      noRecordsFound: 'No records found',
libs/prisma-service/prisma/seed.ts-694-702 (1)

694-702: ⚠️ Potential issue | 🟡 Minor

Password decryption may produce empty string on failure.

At line 694, CryptoJS.AES.decrypt() returns a WordArray. If decryption fails (wrong key, corrupted data), toString(CryptoJS.enc.Utf8) returns an empty string rather than throwing. Line 701 uses this potentially empty password directly.

Consider validating the decrypted password:

🛡️ Proposed validation
   const decryptedPassword = CryptoJS.AES.decrypt(platformAdminData.password, CRYPTO_PRIVATE_KEY);
+  const passwordString = decryptedPassword.toString(CryptoJS.enc.Utf8);
+  if (!passwordString) {
+    throw new Error('Failed to decrypt platform admin password. Check CRYPTO_PRIVATE_KEY.');
+  }
   const token = await getKeycloakToken();
   const user = {
     username: cachedConfig.platformEmail,
     email: cachedConfig.platformEmail,
     firstName: cachedConfig.platformName,
     lastName: cachedConfig.platformName,
-    password: decryptedPassword.toString(CryptoJS.enc.Utf8)
+    password: passwordString
   };
libs/prisma-service/prisma/seed.ts-546-550 (1)

546-550: ⚠️ Potential issue | 🟡 Minor

Potential access to uninitialized cachedConfig.

updateClientId accesses cachedConfig.platformEmail at line 547, but cachedConfig is only populated by getPlatformConfig(). While main() calls getPlatformConfig() before updateClientId(), the function is exported and could be called independently, causing a runtime error.

Consider adding a guard or making the dependency explicit:

🛡️ Proposed defensive check
 export const updateClientId = async (): Promise<void> => {
   const { KEYCLOAK_MANAGEMENT_CLIENT_ID, CRYPTO_PRIVATE_KEY } = process.env;

   if (!KEYCLOAK_MANAGEMENT_CLIENT_ID || !CRYPTO_PRIVATE_KEY) {
     throw new Error('Missing required environment variables');
   }

+  if (!cachedConfig) {
+    throw new Error('Platform config not loaded. Call getPlatformConfig() first.');
+  }
+
   const OLD_CLIENT_ID = process.env.PLATFORM_ADMIN_OLD_CLIENT_ID;
apps/api-gateway/src/ecosystem/ecosystem.controller.ts-543-551 (1)

543-551: ⚠️ Potential issue | 🟡 Minor

Missing UUID validation on orgId parameter.

The orgId parameter should be validated with ParseUUIDPipe for consistency with other endpoints.

apps/ecosystem/src/ecosystem.service.ts-636-642 (1)

636-642: ⚠️ Potential issue | 🟡 Minor

Missing error handling in getTemplatesByOrgId method.

This method lacks the try/catch pattern with ErrorHandler used by similar methods like getIntentTemplatesByOrgId.

apps/api-gateway/src/ecosystem/ecosystem.controller.ts-304-317 (1)

304-317: ⚠️ Potential issue | 🟡 Minor

Inconsistent HTTP status code: returning CREATED for an update operation.

Line 309 returns HttpStatus.CREATED for successful org status update. Use HttpStatus.OK instead.

🔧 Proposed fix
     if (0 < result.count) {
       const finalResponse: IResponse = {
         statusCode: HttpStatus.OK,
         message: ResponseMessages.ecosystem.success.updatedEcosytemOrg
       };
-      return res.status(HttpStatus.CREATED).json(finalResponse);
+      return res.status(HttpStatus.OK).json(finalResponse);
     }
apps/api-gateway/src/ecosystem/ecosystem.controller.ts-265-280 (1)

265-280: ⚠️ Potential issue | 🟡 Minor

Inconsistent HTTP status code: returning CREATED for a delete operation.

Line 272 returns HttpStatus.CREATED for successful deletion. Use HttpStatus.OK instead.

🔧 Proposed fix
     if (0 < result.count) {
       const finalResponse: IResponse = {
         statusCode: HttpStatus.OK,
         message: `${result.count} ${ResponseMessages.ecosystem.success.deletionSuccessfull} for ecosystem id ${deleteUser.ecosystemId}`
       };
-      return res.status(HttpStatus.CREATED).json(finalResponse);
+      return res.status(HttpStatus.OK).json(finalResponse);
     }
apps/api-gateway/src/ecosystem/ecosystem.controller.ts-145-158 (1)

145-158: ⚠️ Potential issue | 🟡 Minor

Inconsistent HTTP status code: returning CREATED for an update operation.

Line 150 returns HttpStatus.CREATED (201) for a successful status update, but the HTTP semantics suggest HttpStatus.OK (200) should be used for updates. The statusCode in the response body correctly shows OK, but the actual HTTP response status is CREATED.

🔧 Proposed fix
     if (result) {
       const finalResponse: IResponse = {
         statusCode: HttpStatus.OK,
         message: `${ResponseMessages.ecosystem.success.updateInvitation} as ${updateInvitation.status}`
       };
-      return res.status(HttpStatus.CREATED).json(finalResponse);
+      return res.status(HttpStatus.OK).json(finalResponse);
     }
apps/ecosystem/src/ecosystem.service.ts-677-685 (1)

677-685: ⚠️ Potential issue | 🟡 Minor

Missing error handling in deleteIntent method.

Unlike other intent CRUD operations (createIntent, updateIntent, getIntents), this method doesn't wrap the repository call in try/catch with ErrorHandler.categorize(). If the repository throws, the error won't be properly formatted as an RpcException.

🛡️ Proposed fix to add consistent error handling
   async deleteIntent(data: { ecosystemId: string; intentId: string; userId: string }): Promise<object> {
     const { ecosystemId, intentId, userId } = data;
 
-    return this.ecosystemRepository.deleteIntent({
-      ecosystemId,
-      intentId,
-      userId
-    });
+    try {
+      return await this.ecosystemRepository.deleteIntent({
+        ecosystemId,
+        intentId,
+        userId
+      });
+    } catch (error) {
+      const errorResponse = ErrorHandler.categorize(error, 'Failed to delete intent');
+      this.logger.error(
+        `[deleteIntent] - ${errorResponse.statusCode}: ${errorResponse.message}`,
+        ErrorHandler.format(error)
+      );
+      throw new RpcException(errorResponse);
+    }
   }
apps/api-gateway/src/ecosystem/ecosystem.service.ts-102-111 (1)

102-111: ⚠️ Potential issue | 🟡 Minor

Incorrect return type annotations.

  • getEcosystemDetailsByUserId returns Promise<user> but should return Promise<ecosystem> based on the method name and microservice implementation
  • getEcosystemOrgDetailsByUserId returns Promise<user> but should return Promise<{ ecosystemRole: { name: string } }[]> based on the microservice

These incorrect types will cause TypeScript to allow invalid usage patterns.

🔧 Proposed fix
+import { ecosystem } from '@prisma/client';
+
-  async getEcosystemDetailsByUserId(userId: string): Promise<user> {
+  async getEcosystemDetailsByUserId(userId: string): Promise<ecosystem> {
     return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-ecosystem-details-by-userid', { userId });
   }

-  async getEcosystemOrgDetailsByUserId(userId: string, ecosystemId: string): Promise<user> {
+  async getEcosystemOrgDetailsByUserId(userId: string, ecosystemId: string): Promise<{ ecosystemRole: { name: string } }[]> {
     return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-ecosystem-org-details-by-userid', {
       userId,
       ecosystemId
     });
   }
apps/api-gateway/src/ecosystem/ecosystem.controller.ts-88-117 (1)

88-117: ⚠️ Potential issue | 🟡 Minor

Error handling swallows stack trace and may leak internal details.

The try/catch block catches all errors and returns a generic 500 response for non-conflict errors, which loses valuable debugging information. The error message from ConflictException is directly exposed to the client without sanitization.

Consider letting the CustomExceptionFilter handle errors consistently, or at least log the error before returning a generic response.

♻️ Suggested improvement
     try {
       await this.ecosystemService.inviteMemberToEcosystem(
         inviteMemberToEcosystem.orgId,
         reqUser.id,
         inviteMemberToEcosystem.ecosystemId
       );

       const finalResponse: IResponse = {
         statusCode: HttpStatus.CREATED,
         message: ResponseMessages.ecosystem.success.memberInviteSucess
       };
       return res.status(HttpStatus.CREATED).json(finalResponse);
     } catch (error) {
       if (error instanceof ConflictException || HttpStatus.CONFLICT === error.status) {
         return res.status(HttpStatus.CONFLICT).json({
-          status: HttpStatus.CONFLICT,
+          statusCode: HttpStatus.CONFLICT,
           message: error.message
         });
       }

-      const finalResponse: IResponse = {
-        statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
-        message: ResponseMessages.errorMessages.serverError
-      };
-
-      return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(finalResponse);
+      // Let the global exception filter handle unexpected errors
+      throw error;
     }
apps/api-gateway/src/ecosystem/ecosystem.controller.ts-599-612 (1)

599-612: ⚠️ Potential issue | 🟡 Minor

Missing UUID validation on id parameter.

The id parameter lacks ParseUUIDPipe validation, unlike similar endpoints in this controller (e.g., getIntentTemplateById at line 566). This inconsistency could allow malformed IDs to reach the service layer.

🔧 Proposed fix
   async updateIntentTemplate(
-    `@Param`('id') id: string,
+    `@Param`(
+      'id',
+      new ParseUUIDPipe({
+        exceptionFactory: (): Error => {
+          throw new BadRequestException(ResponseMessages.oid4vpIntentToTemplate.error.invalidId);
+        }
+      })
+    )
+    id: string,
     `@Body`() updateIntentTemplateDto: UpdateIntentTemplateDto,
apps/api-gateway/src/ecosystem/ecosystem.service.ts-119-121 (1)

119-121: ⚠️ Potential issue | 🟡 Minor

Payload structure inconsistency with other methods.

This method sends id directly as a primitive while other methods wrap IDs in objects (e.g., deleteIntentTemplate sends { id }). This inconsistency was also flagged in the microservice controller review - they should be aligned.

🔧 Suggested alignment with other methods
   async getIntentTemplateById(id: string): Promise<object> {
-    return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-intent-template-by-id', id);
+    return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-intent-template-by-id', { id });
   }

Note: This requires the corresponding change in apps/ecosystem/src/ecosystem.controller.ts as noted in the earlier review.

apps/api-gateway/src/platform/platform.controller.ts-212-222 (1)

212-222: ⚠️ Potential issue | 🟡 Minor

Missing validation for environment variables in QR code URL construction.

The URL is constructed using process.env.API_GATEWAY_PROTOCOL and process.env.API_ENDPOINT without checking if they are defined. If either is missing, the URL will contain "undefined", producing an invalid QR code.

🛡️ Proposed fix to add validation
   async getQrCode(`@Param`('referenceId') referenceId: string, `@Res`() res: Response): Promise<void> {
+    if (!process.env.API_GATEWAY_PROTOCOL || !process.env.API_ENDPOINT) {
+      throw new BadRequestException('API gateway configuration is incomplete');
+    }
     const url = `${process.env.API_GATEWAY_PROTOCOL}://${process.env.API_ENDPOINT}/invitation/${referenceId}`;
     // Generate QR code as a buffer
     const qrCodeBuffer = await QRCode.toBuffer(url);
apps/api-gateway/src/ecosystem/ecosystem.controller.ts-626-634 (1)

626-634: ⚠️ Potential issue | 🟡 Minor

Missing UUID validation on id parameter for delete operation.

Same issue as the update endpoint - add ParseUUIDPipe for consistency and input validation.

🔧 Proposed fix
-  async deleteIntentTemplate(`@Param`('id') id: string, `@Res`() res: Response): Promise<Response> {
+  async deleteIntentTemplate(
+    `@Param`(
+      'id',
+      new ParseUUIDPipe({
+        exceptionFactory: (): Error => {
+          throw new BadRequestException(ResponseMessages.oid4vpIntentToTemplate.error.invalidId);
+        }
+      })
+    )
+    id: string,
+    `@Res`() res: Response
+  ): Promise<Response> {
🧹 Nitpick comments (15)
libs/org-roles/enums/index.ts (1)

14-17: Consider removing duplicate enum or referencing OrgRoles.

EcosystemRoles duplicates values already defined in OrgRoles. This creates maintenance burden—if values change, both enums must be updated.

♻️ Proposed refactor to reference OrgRoles
 export enum EcosystemRoles {
-  ECOSYSTEM_LEAD = 'Ecosystem Lead',
-  ECOSYSTEM_MEMBER = 'Ecosystem Member'
+  ECOSYSTEM_LEAD = OrgRoles.ECOSYSTEM_LEAD,
+  ECOSYSTEM_MEMBER = OrgRoles.ECOSYSTEM_MEMBER
 }

Alternatively, if EcosystemRoles is used for type narrowing, consider using a union type instead:

export type EcosystemRoles = OrgRoles.ECOSYSTEM_LEAD | OrgRoles.ECOSYSTEM_MEMBER;
apps/api-gateway/src/ecosystem/dtos/delete-ecosystem-users.ts (2)

14-20: Redundant @IsString({ each: true }) decorator.

@IsUUID('4', { each: true }) already validates that each element is a valid UUID string. The additional @IsString check is redundant.

♻️ Proposed simplification
   `@IsArray`({ message: 'orgId must be an array' })
   `@ArrayNotEmpty`({ message: 'orgId cannot be empty' })
   `@IsUUID`('4', { each: true })
-  `@IsString`({ each: true })
   `@Transform`(({ value }) => Array.isArray(value) ? value.map(v => v.trim()) : value
   )
   orgIds: string[];

22-27: Redundant @IsString decorator for ecosystemId.

Similar to above, @IsUUID() already validates that the value is a valid UUID string.

♻️ Proposed simplification
   `@ApiProperty`({ example: '61ec22e3-9158-409d-874d-345ad2fc51e4' })
   `@IsUUID`()
   `@IsNotEmpty`({ message: 'ecosystemId is required' })
-  `@IsString`({ message: 'ecosystemId should be a string' })
   `@Transform`(({ value }) => value?.trim())
   ecosystemId: string;
libs/prisma-service/prisma/migrations/20260114071535_create_ecosystem/migration.sql (1)

1-17: Consider adding unique constraint on ecosystem name.

The ecosystem table allows duplicate names since there's no unique constraint. If ecosystem names should be unique across the platform, consider adding a unique index. If duplicates are intentional (e.g., soft-deleted ecosystems), this is acceptable.

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

1149-1169: Potential race condition in deleteIntent.

The method performs a findFirst to check existence, then a separate deleteMany. Between these operations, another process could delete the intent, causing inconsistent state. Since the FK constraint is ON DELETE RESTRICT, there's no cascade risk, but the operation could be simplified.

Consider using a single delete operation:

♻️ Simplified delete with existence check
   async deleteIntent(data: { ecosystemId: string; intentId: string; userId: string }): Promise<intents> {
-    const intent = await this.prisma.intents.findFirst({
-      where: {
-        id: data.intentId,
-        ecosystemId: data.ecosystemId
-      }
-    });
-
-    if (!intent) {
-      throw new NotFoundException('Intent not found in the given ecosystem');
-    }
-
-    await this.prisma.intents.deleteMany({
-      where: {
-        id: data.intentId,
-        ecosystemId: data.ecosystemId
-      }
-    });
-
-    return intent;
+    try {
+      return await this.prisma.intents.delete({
+        where: {
+          id: data.intentId,
+          // Add composite where if schema supports it, or verify ecosystemId after fetch
+        }
+      });
+    } catch (error) {
+      if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2025') {
+        throw new NotFoundException('Intent not found in the given ecosystem');
+      }
+      throw error;
+    }
   }

Note: The current implementation works correctly; this is an optimization suggestion.


1073-1087: Avoid any type for where clause.

Line 1075 uses any type for the where clause. Consider using Prisma's generated types for type safety:

♻️ Use Prisma types
   async getIntents(ecosystemId: string, intentId?: string): Promise<intents[]> {
-    // eslint-disable-next-line `@typescript-eslint/no-explicit-any`
-    const where: any = {
+    const where: Prisma.intentsWhereInput = {
       ecosystemId // ✅ ALWAYS applied
     };
apps/ecosystem/interfaces/ecosystem.interfaces.ts (1)

44-58: Consider renaming to EcosystemOrgAgent to avoid confusion with existing OrgAgent interfaces.

This OrgAgent interface has a fundamentally different structure from the OrgAgent definitions in five other modules (connection, issuance, oid4vc-issuance, oid4vp-verifier, x509). The existing interfaces include audit tracking fields (createDateTime, createdBy, lastChangedDateTime, lastChangedBy), an agentId, and an organisation field, while the ecosystem version omits these and instead includes agentSpinUpStatus, walletName, agentsTypeId, and orgId.

Since this is currently scoped to the ecosystem module with no cross-module imports, there's no immediate type conflict. However, the different naming could cause confusion if future code attempts to reuse or reference OrgAgent types across modules. Renaming to EcosystemOrgAgent would make the distinction explicit and prevent potential mistakes.

apps/api-gateway/src/authz/guards/ecosystem-swagger.filter.ts (1)

13-28: Prune only HTTP operations and drop empty tag entries.
After deletions, a path can be left with only non-operation keys (e.g., parameters), and the root tags list may still include ecosystem with no operations. Consider filtering only HTTP methods and removing empty paths/tags to keep the document clean. Please verify against your @nestjs/swagger/OpenAPI PathItem shape for the current version.

♻️ Suggested refactor
+    const httpMethods = new Set(['get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace']);
     if (!enabled) {
       if (!document.paths) {
         return document;
       }
       Object.keys(document.paths).forEach((path) => {
-        Object.keys(document.paths[path]).forEach((method) => {
-          const operation = document.paths[path][method];
+        const pathItem = document.paths[path];
+        Object.keys(pathItem).forEach((method) => {
+          if (!httpMethods.has(method)) {
+            return;
+          }
+          const operation = pathItem[method];
 
           if (operation.tags?.includes('ecosystem')) {
-            delete document.paths[path][method];
+            delete pathItem[method];
           }
         });
 
-        if (0 === Object.keys(document.paths[path]).length) {
+        const hasOps = Object.keys(pathItem).some((k) => httpMethods.has(k));
+        if (!hasOps) {
           delete document.paths[path];
         }
       });
+      if (document.tags) {
+        document.tags = document.tags.filter((t) => t.name !== 'ecosystem');
+      }
     }
apps/ecosystem/dtos/update-intent.dto.ts (1)

1-11: Add @ApiProperty decorators to ID fields for complete Swagger documentation and pattern consistency.

While these fields are populated from URL parameters and decorators (bypassing the whitelist validation), they lack @ApiProperty decorators, preventing them from appearing in the OpenAPI schema. This creates a documentation gap in Swagger. Additionally, this breaks the pattern established by IntentBaseDto, which is fully decorated. Add @ApiProperty to ensure consistency and accurate API documentation.

Suggested addition
-import { ApiExtraModels } from '@nestjs/swagger';
+import { ApiExtraModels, ApiProperty } from '@nestjs/swagger';
 import { IntentBaseDto } from './intent-base.dto';
 
 `@ApiExtraModels`()
 export class UpdateIntentDto extends IntentBaseDto {
+  `@ApiProperty`()
   intentId: string;
 
+  `@ApiProperty`()
   ecosystemId: string;
 
+  `@ApiProperty`()
   userId: string;
 }
apps/api-gateway/src/ecosystem/ecosystem.module.ts (1)

6-24: Simplify module imports to avoid unnecessary heavyweight dependencies.

The gateway's ecosystem module imports the full EcosystemServiceModule but only needs EcosystemRepository (used in authz guards). Importing the entire app module brings OrganizationModule, UserModule, PrismaService, and other providers that the gateway never uses. Additionally, the gateway registers its own NATS_CLIENT separately despite the imported module also providing one, creating redundancy.

Consider exporting EcosystemRepository from a lightweight dedicated module or importing it directly, rather than coupling to the full ecosystem app module.

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

32-38: Unused import: user from @prisma/client.

The user type imported from @prisma/client on line 32 is used as parameter type in createInvitation, getInvitations, and updateEcosystemConfig endpoints, but these endpoints already have guards that validate the user. Consider using the more descriptive IUserRequestInterface type that's already imported (line 20) for consistency with other endpoints in this controller (getAllSchema, getAllCredDefs).


240-253: Consider consistent response structure.

This endpoint constructs the response inline rather than using the IResponse interface pattern followed by other endpoints in this controller. While functionally correct, consider using the same pattern for consistency:

♻️ Suggested refactor for consistency
   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);
   }
apps/api-gateway/src/ecosystem/ecosystem.controller.ts (1)

423-429: Hardcoded success messages instead of ResponseMessages constants.

Intent template endpoints use hardcoded strings like 'Intent template created successfully' instead of centralized ResponseMessages constants used elsewhere in the codebase. This affects maintainability and i18n support.

Consider adding these messages to ResponseMessages.oid4vpIntentToTemplate or a similar namespace.

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

23-26: Logger instance is declared but never used.

The logger at line 26 is instantiated but none of the handler methods use it for logging. Consider either using it for request/error logging or removing it to reduce dead code.

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

118-139: Consider using ErrorHandler for consistent error handling.

This method creates custom HttpException instances while other methods in this service use ErrorHandler.categorize() and RpcException. Consider using the same pattern for consistency.

Comment on lines +37 to +49
export class UpdateEcosystemInvitationDto {
@ApiProperty({ enum: Invitation, example: Invitation.ACCEPTED })
@Transform(({ value }) => ('string' === typeof value ? value.toLowerCase() : value))
@IsEnum(Invitation, { message: `Status must be one of: ${Object.values(Invitation).join(', ')}` })
@IsNotEmpty({ message: 'Status is required' })
status: Invitation;

@ApiProperty({ example: '61ec22e3-9158-409d-874d-345ad2fc51e4' })
@IsUUID()
@IsNotEmpty({ message: 'ecosystemId is required' })
@IsString({ message: 'ecosystemId should be a string' })
@Transform(({ value }) => value?.trim())
ecosystemId: string;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all usages of UpdateEcosystemInvitationDto
rg -n --type=ts 'UpdateEcosystemInvitationDto' -C 5

Repository: credebl/platform

Length of output: 3673


🏁 Script executed:

#!/bin/bash
# Get the full updateEcosystemInvitationStatus endpoint implementation
sed -n '131,170p' apps/api-gateway/src/ecosystem/ecosystem.controller.ts

Repository: credebl/platform

Length of output: 1294


🏁 Script executed:

#!/bin/bash
# Find the ecosystemService.updateEcosystemInvitationStatus implementation
rg -n 'updateEcosystemInvitationStatus' --type=ts -A 15 | head -60

Repository: credebl/platform

Length of output: 4694


🏁 Script executed:

#!/bin/bash
# Find the ecosystem.service.ts updateEcosystemInvitationStatus method
rg -n 'updateEcosystemInvitationStatus' apps/ecosystem/src/ecosystem.service.ts -A 25

Repository: credebl/platform

Length of output: 3655


Make ecosystemId optional in UpdateEcosystemInvitationDto to support the deferred-ecosystem workflow.

The ecosystem_invitations model allows ecosystemId to be null, supporting a workflow where invitations are created before an ecosystem is assigned. However, the current DTO requires ecosystemId, which would block updates to invitations created in this deferred state. The service code's null check on result?.ecosystemId (line 327 of ecosystem.service.ts) confirms that null values are expected.

Suggested change
-  `@ApiProperty`({ example: '61ec22e3-9158-409d-874d-345ad2fc51e4' })
-  `@IsUUID`()
-  `@IsNotEmpty`({ message: 'ecosystemId is required' })
-  `@IsString`({ message: 'ecosystemId should be a string' })
-  `@Transform`(({ value }) => value?.trim())
-  ecosystemId: string;
+  `@ApiPropertyOptional`({ example: '61ec22e3-9158-409d-874d-345ad2fc51e4' })
+  `@IsOptional`()
+  `@IsUUID`()
+  `@IsString`({ message: 'ecosystemId should be a string' })
+  `@Transform`(({ value }) => value?.trim())
+  ecosystemId?: string;
🤖 Prompt for AI Agents
In `@apps/api-gateway/src/ecosystem/dtos/send-ecosystem-invitation.ts` around
lines 37 - 49, UpdateEcosystemInvitationDto currently requires ecosystemId which
blocks deferred-ecosystem flows; make the property optional and allow null by
adding `@IsOptional`() and changing the TypeScript type to optional/nullable
(e.g., ecosystemId?: string | null), remove the `@IsNotEmpty`() decorator from the
ecosystemId field, keep `@IsUUID`()/@IsString() and the `@Transform`(trim) so
validations only run when a value is provided; target the
UpdateEcosystemInvitationDto -> ecosystemId property and adjust decorators/type
accordingly.

Comment on lines +10 to +17
COPY package.json ./
COPY pnpm-workspace.yaml ./
#COPY package-lock.json ./

ENV PUPPETEER_SKIP_DOWNLOAD=true

# Install dependencies while ignoring scripts (including Puppeteer's installation)
RUN pnpm i --ignore-scripts
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Missing pnpm lockfile for reproducible builds.

The pnpm-lock.yaml file is not copied before running pnpm i. This means builds are not reproducible and may install different dependency versions across builds.

🔧 Proposed fix
 # Copy package.json and package-lock.json
 COPY package.json ./
 COPY pnpm-workspace.yaml ./
-#COPY package-lock.json ./
+COPY pnpm-lock.yaml ./

 ENV PUPPETEER_SKIP_DOWNLOAD=true

 # Install dependencies while ignoring scripts (including Puppeteer's installation)
-RUN pnpm i --ignore-scripts
+RUN pnpm i --frozen-lockfile --ignore-scripts
🤖 Prompt for AI Agents
In `@Dockerfiles/Dockerfile.ecosystem` around lines 10 - 17, The Dockerfile runs
`RUN pnpm i --ignore-scripts` without copying the pnpm lockfile, making builds
non-reproducible; update the Dockerfile so it copies `pnpm-lock.yaml` into the
image prior to running `pnpm i` (i.e., add a `COPY pnpm-lock.yaml ./` step
before the `RUN pnpm i --ignore-scripts` line), ensuring `package.json`,
`pnpm-workspace.yaml`, and the lockfile are present for deterministic installs.

COPY --from=build /app/node_modules ./node_modules

# Set the command to run the microservice
CMD ["sh", "-c", "cd libs/prisma-service && npx prisma migrate deploy && npx prisma generate && cd ../.. && node dist/apps/ecosystem/main.js"] No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Running migrations in CMD poses risks for multi-replica deployments.

When multiple container instances start simultaneously, they will all attempt to run prisma migrate deploy concurrently, which can cause race conditions or migration failures.

Consider:

  1. Running migrations as a separate init container or job in your orchestration (e.g., Kubernetes Job)
  2. Using a migration lock mechanism
  3. Running migrations as part of CI/CD before deployment
🤖 Prompt for AI Agents
In `@Dockerfiles/Dockerfile.ecosystem` at line 44, The Docker CMD currently runs
migrations ("prisma migrate deploy") at container start which risks concurrent
runs in multi-replica deployments; remove the migration step from the CMD in
Dockerfile.ecosystem (the CMD that executes "cd libs/prisma-service && npx
prisma migrate deploy && npx prisma generate && ...") and instead run migrations
outside the app container (e.g., as a separate init container or Kubernetes Job,
a CI/CD step before rollout, or via a dedicated migration service/lock
mechanism) so only one process performs "prisma migrate deploy" while the app
startup keeps only the generate and node start steps.

Signed-off-by: sujitaw <sujit.sutar@ayanworks.com>
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: 3

🤖 Fix all issues with AI agents
In `@libs/common/src/response-messages/index.ts`:
- Line 234: Update the three incorrect response strings in the response-messages
export: change credentialDefinitionNotFound value from "Credential definition
found" to "Credential definition not found"; change invalidFormatOfIntentId
value to reference the correct field by replacing "ecosystemId" with "intentId"
(e.g., "Invalid format for intentId"); and fix noRecordsFound to a sensible
positive statement like "No records found" instead of "No records not found".
Locate and edit the keys credentialDefinitionNotFound, invalidFormatOfIntentId,
and noRecordsFound in the file to apply these text corrections.
- Line 182: Fix the typos in the response messages by updating the string values
for the relevant keys: change deleteEcosystemMember value from "You are deleted
as a ecosystem member" to "You have been removed as an ecosystem member" (or
"You are deleted as an ecosystem member" → "You are removed as an ecosystem
member"), and correct any other misspelling of "ecosytem" to "ecosystem" (e.g.,
the message at the key near line 193). Locate and edit the entries in
libs/common/src/response-messages/index.ts (keys like deleteEcosystemMember and
the other message containing "ecosytem") to use the corrected grammar and
spelling.
- Around line 203-287: The error messages object contains multiple typos and
grammatical issues; update the specified keys in the exported error object to
use the suggested wording: change orgAlreadyExists value from "Organization is
already exists in ecosystem" to "Organization already exists in ecosystem",
exists from "Ecosystem name already exist" to "Ecosystem name already exists",
signTransactionNotApplicable from "aapllicable" to "applicable",
requestSchemaTransaction from "Error while request schema transaction" to "Error
while requesting schema transaction", updateTransactionError from "Error while
update the transaction" to "Error while updating the transaction",
schemaAlreadyExist / schemaNameAlreadyExist / credDefAlreadyExist values from
"already exist" to "already exists",
OrgOrEcosystemNotFoundExceptionForEndorsementTransaction message change "cant"
to "can't", ecosystemRoleNotMatch change "not match" to "does not match",
orgEcoIdRequired change "OrgId & EcosystemId is required" to "OrgId &
EcosystemId are required", ecosystemMembersNotExists change "does not exists" to
"do not exist", ecosystemNotExists change "does not exists" to "does not exist",
and remove the leading space in the message for checkFailed; edit these string
literals in the error object in libs/common/src/response-messages/index.ts
accordingly.
🧹 Nitpick comments (3)
libs/prisma-service/prisma/schema.prisma (3)

738-755: Consider using a proper relation for ledgers instead of Json.

The ledgers field is defined as Json?, but there's an existing ledgers model in the schema (lines 275-289). Using a Json field bypasses referential integrity and makes querying/filtering by ledger properties less efficient.

If an ecosystem can have multiple ledgers, consider a many-to-many relation table. If it's configuration metadata that doesn't map cleanly to the existing ledgers model, the Json field is acceptable—please clarify the intent.


757-766: Missing audit fields createdBy and lastChangedBy.

The ecosystem_roles model lacks createdBy and lastChangedBy fields that are present in most other models (e.g., ecosystem, ecosystem_orgs, org_roles). This inconsistency could complicate audit trails.

Proposed fix
 model ecosystem_roles {
   id                  String    `@id` `@default`(uuid()) `@db.Uuid`
   name                String    `@unique`
   description         String
   createDateTime      DateTime  `@default`(now()) `@db.Timestamptz`(6)
+  createdBy           String    `@default`("1")
   lastChangedDateTime DateTime  `@default`(now()) `@db.Timestamptz`(6)
+  lastChangedBy       String    `@default`("1")
   deletedAt           DateTime? `@db.Timestamp`(6)

   ecosystemOrgs ecosystem_orgs[]
 }

789-806: Missing relation for invitedOrg to organisation model.

The invitedOrg field stores an organisation UUID but lacks a foreign key relation. This means:

  • No referential integrity at the database level
  • No Prisma-generated navigation property for joins

Based on learnings, deletions involving invitedOrg are handled at the application level, but having the relation defined would still improve query ergonomics and data integrity.

Proposed fix
 model ecosystem_invitations {
   id                  String    `@id` `@default`(uuid()) `@db.Uuid`
   email               String    
   status              String
   userId              String?   `@db.Uuid`
   type                String
   ecosystemId         String?   `@db.Uuid`
   invitedOrg          String?   `@db.Uuid`
   createDateTime      DateTime  `@default`(now()) `@db.Timestamptz`(6)
   createdBy           String    `@db.Uuid`
   lastChangedDateTime DateTime  `@default`(now()) `@db.Timestamptz`(6)
   lastChangedBy       String    `@db.Uuid`
   deletedAt           DateTime? `@db.Timestamp`(6)

   ecosystem ecosystem? `@relation`(fields: [ecosystemId], references: [id])
   user user? `@relation`(fields: [userId], references: [id])
+  organisation organisation? `@relation`(fields: [invitedOrg], references: [id])
   @@unique([email, ecosystemId])
 }

You would also need to add the backward relation in the organisation model:

 model organisation {
   ...
   ecosystemOrgs          ecosystem_orgs[]
+  ecosystemInvitations   ecosystem_invitations[]
 }

Signed-off-by: sujitaw <sujit.sutar@ayanworks.com>
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: 1

🤖 Fix all issues with AI agents
In `@libs/common/src/response-messages/index.ts`:
- Line 193: Rename the typo key updatedEcosytemOrg to updatedEcosystemOrg in the
response messages export and update any usages to the new key; specifically
change the key in the response-messages index export (symbol: updatedEcosytemOrg
-> updatedEcosystemOrg) and update the reference in the EcosystemController code
where the old key is used (symbol: updatedEcosytemOrg) to the corrected
updatedEcosystemOrg so both definition and usage match.

updateInvitation: 'Status for ecosystem invitation updated successfully',
deletionSuccessfull: 'Record deleted successfully',
userStatusUpdated: 'User status updated successfully',
updatedEcosytemOrg: 'Updated ecosystem org successfully',
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, check if the file exists and examine the context around line 193
if [ -f "libs/common/src/response-messages/index.ts" ]; then
  echo "=== File exists. Showing context around line 193 ==="
  sed -n '185,200p' libs/common/src/response-messages/index.ts | cat -n
else
  echo "File not found. Listing directory structure:"
  find libs -name "*response*" -type f 2>/dev/null | head -20
fi

Repository: credebl/platform

Length of output: 1322


🏁 Script executed:

#!/bin/bash
# Search for all usages of the misspelled key
echo "=== Searching for 'updatedEcosytemOrg' usages ==="
rg -n 'updatedEcosytemOrg' --type ts --type js --type tsx --type jsx

Repository: credebl/platform

Length of output: 154


🏁 Script executed:

#!/bin/bash
# Also search for the corrected version to see if it exists
echo "=== Searching for 'updatedEcosystemOrg' (corrected version) ==="
rg -n 'updatedEcosystemOrg' --type ts --type js --type tsx --type jsx

Repository: credebl/platform

Length of output: 168


🏁 Script executed:

#!/bin/bash
# Get a broader view of the ecosystem-related keys in the response-messages file
echo "=== Searching for ecosystem-related keys in index.ts ==="
rg -n 'cosystem|cosytem' libs/common/src/response-messages/ -A 1 -B 1

Repository: credebl/platform

Length of output: 10350


🏁 Script executed:

#!/bin/bash
# Search for usages of the misspelled key without file type filter
echo "=== Searching for 'updatedEcosytemOrg' usages (all files) ==="
rg -n 'updatedEcosytemOrg' 2>/dev/null || echo "No matches found or rg error"

Repository: credebl/platform

Length of output: 362


🏁 Script executed:

#!/bin/bash
# Search for ResponseMessages references to ecosystem
echo "=== Searching for ResponseMessages.ecosystem usages ==="
rg -n 'ResponseMessages\.ecosystem' 2>/dev/null | head -30 || echo "No matches"

Repository: credebl/platform

Length of output: 4249


🏁 Script executed:

#!/bin/bash
# Search for any references to this specific key
echo "=== Searching for response references with updatedEcosytem ==="
rg -n 'updatedEcosytem' 2>/dev/null | head -50 || echo "No matches"

Repository: credebl/platform

Length of output: 363


🏁 Script executed:

#!/bin/bash
# Check the complete ecosystem.success object structure
echo "=== Getting full ecosystem.success object ==="
sed -n '163,202p' libs/common/src/response-messages/index.ts | cat -n

Repository: credebl/platform

Length of output: 2870


Rename updatedEcosytemOrg to updatedEcosystemOrg to fix the key name typo.

The key name contains "Ecosytem" instead of "Ecosystem" and is actively referenced in the codebase at apps/api-gateway/src/ecosystem/ecosystem.controller.ts:307. Updating this requires changes in two locations:

  1. libs/common/src/response-messages/index.ts:193 — rename the key
  2. apps/api-gateway/src/ecosystem/ecosystem.controller.ts:307 — update the reference
🤖 Prompt for AI Agents
In `@libs/common/src/response-messages/index.ts` at line 193, Rename the typo key
updatedEcosytemOrg to updatedEcosystemOrg in the response messages export and
update any usages to the new key; specifically change the key in the
response-messages index export (symbol: updatedEcosytemOrg ->
updatedEcosystemOrg) and update the reference in the EcosystemController code
where the old key is used (symbol: updatedEcosytemOrg) to the corrected
updatedEcosystemOrg so both definition and usage match.

Signed-off-by: sujitaw <sujit.sutar@ayanworks.com>
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots

See analysis details on SonarQube Cloud

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 304-310: The response for successful updates in the update handler
returns HTTP 201 (HttpStatus.CREATED) while the finalResponse.statusCode is
HttpStatus.OK; update the controller (in the block that checks result.count > 0)
to send a 200 response by changing res.status(HttpStatus.CREATED) to
res.status(HttpStatus.OK) (or use finalResponse.statusCode) so the HTTP status
matches the update operation and the message in ecosystem.controller.ts.
- Around line 145-151: The handler currently returns HTTP 201 on successful
invitation updates; change it to return 200 to match the operation and the
response body. In the block that checks `if (result)`, update the
`res.status(...)` call from `HttpStatus.CREATED` to `HttpStatus.OK` and ensure
the `finalResponse.statusCode` remains `HttpStatus.OK` (no other body changes).
Look for `result`, `finalResponse`,
`ResponseMessages.ecosystem.success.updateInvitation`,
`updateInvitation.status`, and the `res.status(...).json(...)` call to make this
single-line status change.
- Around line 265-279: In deleteEcosystemUsers, the response status codes are
incorrect: when ecosystemService.deleteEcosystemOrgs returns a positive
result.count, change the HTTP status from HttpStatus.CREATED to HttpStatus.OK
and set finalResponse.statusCode to HttpStatus.OK (keep the success message),
and when no records are deleted change the returned status from
HttpStatus.BAD_REQUEST to HttpStatus.NOT_FOUND and set finalResponse.statusCode
to HttpStatus.NOT_FOUND using ResponseMessages.ecosystem.error.noRecordsFound;
update the res.status(...) calls accordingly in the deleteEcosystemUsers method.
- Around line 71-90: In inviteMemberToEcosystem replace the plain throw new
Error('Missing request user id') with a NestJS HTTP exception (e.g., throw new
BadRequestException('Missing request user id') or throw new
UnauthorizedException(...) as appropriate for your auth logic) so the client
receives a 4xx, and update the `@ApiResponse` on the same handler from status:
HttpStatus.OK to status: HttpStatus.CREATED to match the handler's 201 response
in inviteMemberToEcosystem.

@pranalidhanavade pranalidhanavade merged commit 946ecd2 into main Jan 31, 2026
7 of 8 checks passed
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.

3 participants