Skip to content

fix(1559): upgrade to Prisma v7 with config restructuring & import updates#1568

Open
sahilkhude117 wants to merge 5 commits intocredebl:mainfrom
sahilkhude117:fix-1559/prisma-v7-upgrade
Open

fix(1559): upgrade to Prisma v7 with config restructuring & import updates#1568
sahilkhude117 wants to merge 5 commits intocredebl:mainfrom
sahilkhude117:fix-1559/prisma-v7-upgrade

Conversation

@sahilkhude117
Copy link

@sahilkhude117 sahilkhude117 commented Feb 17, 2026

This PR upgrades the project to Prisma v7 and applies all required structural, configuration, client, seed, and import updates.


Main Changes

Core Prisma Upgrade

  • Added external prisma.config.ts
  • Updated schema.prisma
  • Updated README.md

Prisma Client Adjustments

  • Updated cli.ts
    • Added pg-adapter for pooled database support
  • Updated prisma-service.service.ts
    • Adjusted client initialization to align with Prisma v7

Seed & Script Fixes

  • Updated seed.ts
  • updated path for scripts with right paths
  • Updated:
    • scripts/geo_location_data_import.sh
    • .env.demo
    • .env.sample

Import & Module Refactoring

  • Added module alias wrapper in package.json i.e @credebl/prisma for libs/prisma-service/generated/prisma to easily import client. with @credebl/prisma/client.
  • Updated tsconfig.json paths configuration
  • Updated all the old import from @primsa/client to @credebl/prisma/client (which maps to libs/prisma-service/generated/prisma/client)

Summary by CodeRabbit

  • Chores
    • Migrated database client to a new version with improved connection pooling capabilities.
    • Updated internal dependencies and path configurations.
    • Enhanced data model with additional relationship mappings and audit tracking fields across entities.

Signed-off-by: sahilkhude117 <sahilkhude11@gmail.com>
Signed-off-by: sahilkhude117 <sahilkhude11@gmail.com>
Signed-off-by: sahilkhude117 <sahilkhude11@gmail.com>
Signed-off-by: sahilkhude117 <sahilkhude11@gmail.com>
Signed-off-by: sahilkhude117 <sahilkhude11@gmail.com>
Copilot AI review requested due to automatic review settings February 17, 2026 14:18
@coderabbitai
Copy link

coderabbitai bot commented Feb 17, 2026

📝 Walkthrough

Walkthrough

This pull request refactors the project's Prisma integration by migrating from standard @prisma/client to a custom @credebl/prisma/client package, reorganizing prisma-related files from libs/prisma/ to libs/prisma-service/, upgrading Prisma from v5 to v7.4.0 with PostgreSQL adapter support, and restructuring the Prisma schema with expanded models, relations, and audit fields.

Changes

Cohort / File(s) Summary
Environment Configuration
.env.demo, .env.sample
Updated script path references from /prisma/scripts/... to /libs/prisma-service/prisma/scripts/... for geo-location and client credential data imports.
Git & Root Configuration
.gitignore, prisma.config.ts, tsconfig.json, package.json
Added prisma-service generated path to .gitignore; created new Prisma config file; updated module aliases to point to libs/prisma-service/generated/prisma; upgraded Prisma to v7.4.0 with PostgreSQL adapter dependency.
Prisma Service Core
libs/prisma-service/cli.ts, libs/prisma-service/src/prisma-service.service.ts, libs/prisma-service/prisma/seed.ts
Integrated PrismaPg adapter for PostgreSQL connection pooling; updated PrismaClient import paths to generated client; modified seed data file path to libs/prisma-service location.
Prisma Schema & Scripts
libs/prisma-service/prisma/schema.prisma, libs/prisma-service/prisma/scripts/geo_location_data_import.sh
Major schema restructure adding primary keys (id fields), audit fields (createdBy/lastChangedBy), new relations, and four new enums (RecordType, UserRole, CloudWalletType, SignerOption); updated CSV import paths in geo-location script.
Documentation
README.md
Removed directory change commands before Prisma CLI invocations; scripts now assume correct working directory context.
Agent Service
apps/agent-service/src/...
Updated Prisma client import sources from @prisma/client to @credebl/prisma/client across controller, service, interface, and repository files.
API Gateway - Core
apps/api-gateway/common/interface.ts, apps/api-gateway/src/authz/*, apps/api-gateway/src/agent-service/*
Migrated all Prisma imports to @credebl/prisma/client; updated type references for user and Prisma types across authentication, authorization, and agent service modules.
API Gateway - Business Logic
apps/api-gateway/src/cloud-wallet/*, apps/api-gateway/src/connection/*, apps/api-gateway/src/ecosystem/*, apps/api-gateway/src/issuance/*
Updated Prisma client import paths and adjusted method signature formatting; organization.repository.ts includes logic updates for org_agents array normalization and explicit type casting.
API Gateway - OID4VC & Verification
apps/api-gateway/src/oid4vc-*/dtos/*, apps/api-gateway/src/oid4vc-issuance/*, apps/api-gateway/src/oid4vc-verification/*, apps/api-gateway/src/x509/*
Updated Prisma type imports (SignerOption, user, oidc_issuer, oid4vp_verifier) to use @credebl/prisma/client; formatting adjustments in controller/service signatures.
API Gateway - User & Platform
apps/api-gateway/src/organization/*, apps/api-gateway/src/platform/*, apps/api-gateway/src/user/*, apps/api-gateway/src/verification/*
Migrated all user, organisation, and verification-related Prisma imports to @credebl/prisma/client; no logic changes beyond import path updates.
Cloud Wallet Service
apps/cloud-wallet/src/cloud-wallet.repository.ts
Updated cloud_wallet_user_info and user imports to @credebl/prisma/client; reformatted ICloudWalletDetails imports with minor field organization changes (20/-7 lines).
Connection & Ecosystem Services
apps/connection/src/..., apps/ecosystem/...
Updated Prisma client imports across repositories, controllers, and services; connection.repository.ts includes minor formatting adjustments; ecosystem.interfaces.ts imports Prisma and JsonValue from new paths.
Issuance & Ledger Services
apps/issuance/src/..., apps/ledger/src/...
Updated Prisma imports to @credebl/prisma/client; credential-definition.repository.ts substantially refactored with 10 new public methods for schema/credential-definition queries and filtering; ledger service/repository added 4 new public methods for network and schema retrieval.
OID4VC Issuance & Verification
apps/oid4vc-issuance/..., apps/oid4vc-verification/...
Updated Prisma client import paths across interfaces, helpers, controllers, and services; Oid4vcVerificationModule class renamed from Oid4vpModule; test import path corrected; oid4vc-verification.service.ts reduced by 1 line with import consolidation.
Organization & User Services
apps/organization/..., apps/user/...
Updated Prisma imports to @credebl/prisma/client; organization.repository.ts includes logic normalization for org_agents array handling and type casting; user services updated with import path changes; user-device.repository.ts extended with new createdBy/lastChangedBy fields in FidoMultiDevicePayload.
Additional Services
apps/utility/src/..., apps/verification/src/..., apps/webhook/src/..., apps/x509/src/...
Updated Prisma imports to @credebl/prisma/client across all repositories, controllers, and services; verification.repository.ts wrapped in eslint disable/enable camelcase directives.
Common Libraries
libs/common/src/interfaces/*, libs/http-exception.filter.ts, libs/org-roles/*, libs/user-activity/*, libs/user-org-roles/*
Updated all Prisma type imports from @prisma/client to @credebl/prisma/client; http-exception.filter.ts imports internal prismaNamespace for type resolution; org-roles/repositories added 2 new public methods (getOrgRoles, getOrgRolesByIds); user-org-roles/service.updateUserOrgRole now returns boolean true.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~105 minutes

Possibly related PRs

  • credebl/platform#1534 — Modifies Prisma schema with verification_templates, intents, and intent_templates models alongside schema/generated client path changes.
  • credebl/platform#1540 — Updates ecosystem-related models in libs/prisma-service/prisma/schema.prisma with overlapping schema modifications.
  • credebl/platform#1418 — Refactors Prisma scripts and generated client locations into libs/prisma-service/prisma, directly aligned with environment variable path updates.

Suggested labels

enhancement, refactoring, database, prisma

Suggested reviewers

  • sujitaw
  • RinkalBhojani

Poem

🐰 A Tale of Migration Swift
From prisma lands to credebl's gift,
Schemas expand with audit trails bright,
PostgreSQL pooling holds databases tight,
A hundred files dance in harmony's rhyme,
Infrastructure refined, one import at a time! ✨

🚥 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 title clearly summarizes the main change: upgrading to Prisma v7 with config restructuring and import updates, which aligns with the primary objectives of the PR.
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.

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

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

@sonarqubecloud
Copy link

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Upgrades the repo to Prisma v7, restructures Prisma configuration to use prisma.config.ts, and refactors the codebase to import the generated Prisma client via the @credebl/prisma alias.

Changes:

  • Introduces prisma.config.ts and updates Prisma schema/client generation output paths.
  • Adds @prisma/adapter-pg and updates Prisma client initialization to use the PG adapter.
  • Refactors numerous imports from @prisma/client to @credebl/prisma/client, plus assorted script/path fixes.

Reviewed changes

Copilot reviewed 107 out of 110 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
tsconfig.json Updates @credebl/prisma/* path mapping to generated Prisma client output.
prisma.config.ts Adds Prisma v7 config file pointing to schema/migrations/seed.
pnpm-lock.yaml Locks Prisma v7 + adapter dependencies; shows remaining Prisma v5 client dependency in workspace.
package.json Adds Prisma PG adapter + bumps Prisma packages; updates Jest moduleNameMapper for new alias.
libs/prisma-service/src/prisma-service.service.ts Initializes PrismaClient with @prisma/adapter-pg adapter.
libs/prisma-service/prisma/seed.ts Updates seed to use generated Prisma client + PG adapter; adjusts data file path.
libs/prisma-service/cli.ts Updates CLI to use PG adapter + generated Prisma client.
apps/organization/repositories/organization.repository.ts Adjusts org_agents relation usage and response shaping.
apps/organization/interfaces/organization.interface.ts Updates Prisma imports/types for Prisma v7 + new generation location.
libs/http-exception.filter.ts Refactors Prisma error imports to new generated/aliased locations.
apps/oid4vc-verification/src/oid4vc-verification.module.ts Renames exported module class.
README.md / .env.* / scripts Updates Prisma-related docs and script paths after restructuring.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +56 to +57
"@prisma/adapter-pg": "^7.4.0",
"@prisma/client": "^7.4.0",
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

Prisma v7 requires Node >=20.19 (see @prisma/client@7.4.0 engines in the lockfile), but this repo still advertises engines.node: >=18. This can lead to installs/builds succeeding on unsupported Node versions and failing at runtime or during prisma generate. Update the root engines (and CI/runtime images) to a Prisma v7-compatible Node version, or pin Prisma to a version that supports your declared Node range.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to 10
const { PrismaPg } = require('@prisma/adapter-pg');
const { PrismaClient } = require('generated/prisma/client');
const { createClient } = require('@supabase/supabase-js');
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

require('generated/prisma/client') is a bare module specifier, so Node will try to resolve it from node_modules and this CLI will fail to start. Use a relative path (e.g. ./generated/prisma/client) or the project alias (@credebl/prisma/client) so it resolves correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +17
const connectionString = process.env.POOL_DATABASE_URL as string;
const adapter = new PrismaPg({ connectionString });

Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

POOL_DATABASE_URL is asserted as string and used to create the PrismaPg adapter without validation. When running prisma db seed in environments that only provide DATABASE_URL (common for non-pooled connections), this will fail. Consider falling back to DATABASE_URL and/or emitting a clear error if neither is set.

Copilot uses AI. Check for mistakes.
Comment on lines +509 to +521
// Transform org_agents from single object to array to match interface
if (result && result.org_agents) {
return {
...result,
org_agents: [result.org_agents]
} as IGetOrgById;
}

// Return with empty array if no org_agents
return {
...result,
org_agents: []
} as IGetOrgById;
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

result from findFirst() can be null. The return { ...result, org_agents: [] } path will throw TypeError: Cannot convert undefined or null to object when no organisation matches. Handle the not-found case explicitly before spreading (e.g., return null, throw NotFoundException, or keep the old findFirstOrThrow).

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +2
import { Prisma } from '@credebl/prisma/client';
import { JsonValue } from 'libs/prisma-service/generated/prisma/internal/prismaNamespace';
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

This import will compile to require('libs/prisma-service/generated/prisma/internal/prismaNamespace'), which Node will treat as a package name and fail to resolve at runtime. Use the established alias (@credebl/prisma/internal/prismaNamespace) or another resolvable module path instead of a non-relative libs/... specifier.

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +12
// direct DB string here (directUrl from old primsa.schema file)
url: process.env.DATABASE_URL
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

Typo in comment: primsa.schemaprisma.schema.

Copilot uses AI. Check for mistakes.
Comment on lines 532 to +534
'@prisma/client':
specifier: ^5.1.1
version: 5.22.0(prisma@5.22.0)
version: 5.22.0(prisma@7.4.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.2))
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The lockfile still shows libs/common depending on @prisma/client with specifier: ^5.1.1, which results in @prisma/client@5.22.0 being installed alongside Prisma v7. This mix of major versions is risky and can cause type/runtime mismatches; align workspace package versions (and remove the old specifier) so the repo consistently uses Prisma v7.

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 4
import { Catch, ExceptionFilter, HttpException, HttpStatus, Logger } from '@nestjs/common';
import { RpcException } from '@nestjs/microservices';
import { PrismaClientKnownRequestError, PrismaClientValidationError } from '@prisma/client/runtime/library';
import { PrismaClientKnownRequestError, PrismaClientValidationError } from '@credebl/prisma/internal/prismaNamespace';
import { Observable, throwError } from 'rxjs';
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

HttpExceptionFilter does runtime exception.constructor comparisons, so the imported Prisma error symbols must be the real runtime classes. @credebl/prisma/internal/prismaNamespace is typically a types/namespace export, not the Prisma runtime error module; this may cause Prisma errors to fall through to the default case. Prefer importing these from Prisma’s runtime library entry (or another documented runtime export) so the comparisons work reliably.

Copilot uses AI. Check for mistakes.
Comment on lines 13 to +16
constructor() {
const connectionString = process.env.POOL_DATABASE_URL as string;
const adapter = new PrismaPg({ connectionString });

Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

POOL_DATABASE_URL is asserted as string and passed into PrismaPg without any validation/fallback. If it’s unset, the adapter/client initialization will throw early with a low-signal error. Prefer an explicit fallback (e.g. DATABASE_URL) and/or throw a clear configuration error when neither env var is set.

Copilot uses AI. Check for mistakes.
Comment on lines 49 to +52
}
]
})
export class Oid4vpModule {}
export class Oid4vcVerificationModule {}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The exported module class was renamed to Oid4vcVerificationModule, but apps/oid4vc-verification/src/main.ts still imports/bootstraps Oid4vpModule. This will break compilation/runtime until the main entrypoint is updated to use the new module class name.

Copilot uses AI. Check for mistakes.
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: 18

Caution

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

⚠️ Outside diff range comments (5)
apps/user/repositories/user-device.repository.ts (2)

252-257: ⚠️ Potential issue | 🟡 Minor

Pre-existing bug: return type mismatch — SELECT result typed as BatchPayload.

updateDeviceByCredentialId declares Promise<Prisma.BatchPayload> but executes a SELECT * via $queryRaw, which returns an array of rows, not a BatchPayload. This will silently produce a runtime type mismatch. Consider fixing the return type to match the actual query result (e.g., Promise<user_devices[]>), and also note the same $queryRaw LIKE pattern concern flagged above at Line 150.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/user/repositories/user-device.repository.ts` around lines 252 - 257, The
method updateDeviceByCredentialId is declared to return
Promise<Prisma.BatchPayload> but calls this.prisma.$queryRaw with a SELECT
(user_devices rows), causing a type mismatch; change the return type to match
the actual result (e.g., Promise<user_devices[]> or an appropriate DTO/array
type) and update callers if needed, and ensure the query uses the correct
$queryRaw or $queryRawUnsafe signature on this.prisma.$queryRaw and parameter
interpolation for credentialId to avoid SQL injection or LIKE-pattern issues.

150-153: ⚠️ Potential issue | 🟠 Major

Pre-existing bug: $queryRaw LIKE clause breaks parameterization.

This isn't introduced by this PR, but since you're touching this file — the '%${credentialId}%' inside the tagged template literal doesn't work as intended. Prisma's $queryRaw will parameterize ${credentialId}, but wrapping it inside SQL string quotes with % means the resulting SQL becomes LIKE '%$1%', matching the literal text $1 rather than the variable's value. This also poses a potential SQL injection risk if it falls back to string concatenation.

The correct approach:

Proposed fix
      const getUserDevice = await this.prisma.$queryRaw`
  SELECT * FROM user_devices
-  WHERE credentialId LIKE '%${credentialId}%'
+  WHERE "credentialId" LIKE ${'%' + credentialId + '%'}
   LIMIT 1;
 `;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/user/repositories/user-device.repository.ts` around lines 150 - 153, The
LIKE pattern is currently embedded as a literal string '%${credentialId}%'
inside the tagged $queryRaw, which breaks parameterization and risks SQL
injection; update the query to supply the pattern as a parameter by
concatenating the percent wildcards to credentialId outside the SQL string
(e.g., pass ${`%${credentialId}%`} or use CONCAT/|| with ${credentialId}) so the
binding stays parameterized—look for the this.prisma.$queryRaw call using
credentialId in user-device.repository.ts and replace the '%${credentialId}%'
usage with a parameterized pattern.
apps/oid4vc-issuance/src/oid4vc-issuance.service.ts (1)

200-201: ⚠️ Potential issue | 🔴 Critical

Null-pointer dereference: && should be ||.

If getIssuerDetails is null/undefined, the && operator evaluates the right-hand side, causing a TypeError when accessing .publicIssuerId on a nullish value. This should use || (logical OR) to short-circuit correctly.

🐛 Proposed fix
-      if (!getIssuerDetails && !getIssuerDetails.publicIssuerId) {
+      if (!getIssuerDetails || !getIssuerDetails.publicIssuerId) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/oid4vc-issuance/src/oid4vc-issuance.service.ts` around lines 200 - 201,
The if condition in oid4vc-issuance.service.ts incorrectly uses && and can throw
when getIssuerDetails is nullish; update the check in the block that throws
NotFoundException (using ResponseMessages.oidcIssuer.error.notFound) to use ||
so it short-circuits: i.e., test if (!getIssuerDetails ||
!getIssuerDetails.publicIssuerId) before throwing; adjust any related null-safe
logic in the surrounding method (where getIssuerDetails is used) to match this
corrected guard.
tsconfig.json (1)

59-70: ⚠️ Potential issue | 🟡 Minor

Remove or update stale @credebl/prisma base path mapping.

The base alias "@credebl/prisma" (line 59) maps to "libs/prisma/src", which no longer exists. While no code currently imports from the bare @credebl/prisma path (all imports use wildcards like @credebl/prisma/*), this broken mapping is technical debt. Either remove the alias entirely or update it to point to a valid path in libs/prisma-service/src if the base module is still needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tsconfig.json` around lines 59 - 70, The tsconfig path mapping for the base
alias "@credebl/prisma" is stale (it points to "libs/prisma/src" which no longer
exists); either remove the "@credebl/prisma" entry from the "paths" block or
change its target to a valid location such as "libs/prisma-service/src" (to
match the existing "@credebl/prisma/*" wildcard), and ensure the change keeps
consistency with "@credebl/prisma/*" and "@credebl/prisma-service" mappings so
imports resolve correctly.
package.json (1)

25-27: ⚠️ Potential issue | 🟡 Minor

Remove the prisma.seed field from package.json—it is unsupported in Prisma v7 and will be ignored.

In Prisma v7, the "prisma" block in package.json (including "prisma.seed") was removed and is no longer read. The seed configuration must be defined in prisma.config.ts using the migrations.seed field, as is already done in this project. Keeping this field creates unnecessary confusion and technical debt.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 25 - 27, Remove the legacy Prisma seed entry from
package.json: delete the "prisma" object that contains "seed": "ts-node
prisma/seed.ts" since Prisma v7 no longer supports package.json seed
configuration; rely on the existing prisma.config.ts's migrations.seed instead
to avoid confusion and technical debt.
🧹 Nitpick comments (8)
apps/user/repositories/user-device.repository.ts (1)

35-35: String(userId) casts are consistent but worth questioning.

If userId is already typed as string in the function signature, String(userId) is a no-op. If there's a runtime concern about receiving non-string values from upstream, a validation/assertion at the service boundary would be cleaner than defensive casting inside every repository method.

Also applies to: 55-55, 78-78, 103-103, 122-122

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/user/repositories/user-device.repository.ts` at line 35, The repository
uses defensive casts like String(userId) inside UserDeviceRepository methods;
remove those casts and pass the typed userId through directly (replace
String(userId) with userId) in all occurrences in user-device.repository.ts, and
instead add an explicit validation/assertion for userId at the service boundary
(e.g., in the UserDeviceService methods that call the repository) to ensure
userId is a string (or validate via DTO/schema) before calling repository
methods; update any related tests accordingly.
apps/api-gateway/src/authz/authz.service.ts (1)

18-22: Two separate imports from the same module can be consolidated.

user (Line 18) and Prisma (Line 21) are both imported from @credebl/prisma/client in separate statements. Since user is only used as a type annotation (Line 44), it could use import type as well. Both could be merged into a single statement.

♻️ Optional consolidation
-import { user } from '@credebl/prisma/client';
 import { IRestrictedUserSession, ISessionDetails } from 'apps/user/interfaces/user.interface';
-import type { Prisma } from '@credebl/prisma/client';
+import type { Prisma, user } from '@credebl/prisma/client';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api-gateway/src/authz/authz.service.ts` around lines 18 - 22, The
imports from "@credebl/prisma/client" are split; consolidate them into a single
import and mark type-only imports with "import type" to avoid runtime inclusion:
replace the separate imports of "user" and "Prisma" with one statement importing
both as types (e.g., import type { user, Prisma } from '@credebl/prisma/client')
so references like the type annotation for "user" on the method using
IRestrictedUserSession/ISessionDetails are correctly treated as type-only.
libs/prisma-service/src/prisma-service.service.ts (1)

32-54: Event listeners registered after $connect — events emitted during connection may be missed.

$on('error', ...), $on('warn', ...), and $on('query', ...) are registered after await this.$connect() on line 33. Any log events emitted during the connection phase will be silently dropped. Consider moving the $on registrations before the $connect call.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/prisma-service/src/prisma-service.service.ts` around lines 32 - 54,
onModuleInit currently calls await this.$connect() before registering Prisma
event listeners ($on for 'error','warn','query'), which can miss events emitted
during connection; move the (this as any).$on(...) registration blocks for
'error', 'warn', and 'query' to execute before calling await this.$connect(),
keeping the same handlers/signatures (Prisma.LogEvent, Prisma.QueryEvent) and
then call await this.$connect() so all connection-time events are captured by
the existing listeners.
libs/prisma-service/prisma/schema.prisma (1)

770-770: Stray blank line inside ecosystem_invitations model before the closing @@unique.

Line 770 has an empty line between the user relation (line 769) and the @@unique constraint (line 771). While not a functional issue, it's inconsistent with the formatting of other models in this schema.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/prisma-service/prisma/schema.prisma` at line 770, In the
ecosystem_invitations model remove the stray blank line between the user
relation declaration (the line defining the relation field `user`) and the
model-level constraint `@@unique` so that the `user` relation and the `@@unique`
constraint are adjacent and match the formatting style used by other models;
edit the `ecosystem_invitations` model to delete that empty line and ensure
spacing matches other model blocks.
apps/ledger/src/repositories/ledger.repository.ts (1)

59-109: Duplicated where clause between findMany and count queries.

The filter condition on lines 69–77 and 88–97 is identical. Extract it to a local variable to avoid drift and reduce duplication.

♻️ Suggested refactor
     const { schemaArray, search, pageSize, pageNumber } = data;

+    const whereClause = {
+      schemaLedgerId: {
+        in: schemaArray
+      },
+      OR: [
+        { version: { contains: search, mode: 'insensitive' as const } },
+        { name: { contains: search, mode: 'insensitive' as const } },
+        { schemaLedgerId: { contains: search, mode: 'insensitive' as const } }
+      ]
+    };
+
     const schemasResult: ISchemasResult[] = await this.prisma.schema.findMany({
-      where: {
-        schemaLedgerId: {
-          in: schemaArray
-        },
-        OR: [
-          { version: { contains: search, mode: 'insensitive' } },
-          { name: { contains: search, mode: 'insensitive' } },
-          { schemaLedgerId: { contains: search, mode: 'insensitive' } }
-        ]
-      },
+      where: whereClause,
       take: pageSize,
       skip: (pageNumber - 1) * pageSize,
       orderBy: {
         createDateTime: 'desc'
       }
     });

     const schemasCount = await this.prisma.schema.count({
-      where: {
-        schemaLedgerId: {
-          in: schemaArray
-        },
-        OR: [
-          { version: { contains: search, mode: 'insensitive' } },
-          { name: { contains: search, mode: 'insensitive' } },
-          { schemaLedgerId: { contains: search, mode: 'insensitive' } }
-        ]
-      }
+      where: whereClause
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ledger/src/repositories/ledger.repository.ts` around lines 59 - 109,
Extract the duplicated Prisma filter into a local variable inside
handleGetSchemas and reuse it for both prisma.schema.findMany and
prisma.schema.count: create a const (e.g., schemasWhere) that contains the
schemaLedgerId/in array and the OR search clauses, then pass schemasWhere to the
where option of the findMany call that returns schemasResult and to the count
call that returns schemasCount so the filter logic is defined once and avoids
drift between the two queries.
apps/ledger/src/schema/schema.controller.ts (1)

68-84: Consider extracting the verbose inline return type to a named interface.

This 14-line inline object type makes the method signature harder to read. A dedicated interface (e.g., ISchemaExistResult) would improve clarity and be reusable if the same shape is needed elsewhere.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ledger/src/schema/schema.controller.ts` around lines 68 - 84, The method
schemaExist has a long inline return type; extract that object shape to a named
interface (e.g., ISchemaExistResult) and use ISchemaExistResult[] as the
method's return type. Define the interface with the same properties (id,
createDateTime, createdBy, lastChangedDateTime, lastChangedBy, name, version,
attributes, schemaLedgerId, publisherDid, issuerId, orgId, ledgerId) near other
schema types (or export it from a shared types file) and update schemaExist's
signature to return Promise<ISchemaExistResult[]>, keeping exports/visibility
consistent with how the file uses interfaces.
libs/org-roles/repositories/index.ts (1)

15-40: Missing await on the Prisma findMany call in getAllLedgers-style pattern — but more importantly, inconsistent error handling across methods.

getRole (line 27) and getOrgRoles (line 38) both throw new InternalServerErrorException('Bad Request') — the message "Bad Request" is semantically wrong for a 500 status code. Meanwhile, getOrgRolesByIds (line 60) rethrows the original error. This inconsistency predates this PR, but since the methods are being reformatted anyway, it's worth noting for a future cleanup.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/org-roles/repositories/index.ts` around lines 15 - 40, Update error
handling to be consistent and accurate: in getRole and getOrgRoles replace the
misleading new InternalServerErrorException('Bad Request') with a proper
InternalServerErrorException containing contextual text (e.g., 'Failed
retrieving org roles' or 'Failed retrieving role') and include or preserve the
original error details in the log; ensure getOrgRolesByIds follows the same
pattern (log the error via this.logger.error with the error object/stringified
and then throw a standardized InternalServerErrorException) so all repository
methods (getRole, getOrgRoles, getOrgRolesByIds) uniformly log the original
error and throw a clear 500-level exception message.
apps/connection/src/connection.service.ts (1)

28-30: Consider consolidating duplicate import statements.

Both lines import from the same @credebl/prisma/client module. They can be merged into a single import.

♻️ Proposed consolidation
-import { RecordType, user } from '@credebl/prisma/client';
-import { UserActivityRepository } from 'libs/user-activity/repositories';
-import { agent_invitations } from '@credebl/prisma/client';
+import { RecordType, user, agent_invitations } from '@credebl/prisma/client';
+import { UserActivityRepository } from 'libs/user-activity/repositories';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/connection/src/connection.service.ts` around lines 28 - 30, Consolidate
the duplicate imports from `@credebl/prisma/client` by merging the two import
statements into one that imports RecordType, user, and agent_invitations
together; update the import block in connection.service.ts to reference these
symbols (RecordType, user, agent_invitations) from a single import statement and
remove the redundant import so all Prisma types come from one line.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/ecosystem/interfaces/ecosystem.interfaces.ts`:
- Around line 2-5: Remove the non-standard import of JsonValue from
'@credebl/prisma/internal/prismaNamespace' and replace all uses of the
standalone JsonValue type with Prisma.JsonValue, leveraging the already-imported
Prisma symbol (import { Prisma, PrismaClient } ...). Update any interface/type
declarations that reference JsonValue to use Prisma.JsonValue so the file
follows the standard Prisma v7 pattern used elsewhere.

In
`@apps/ledger/src/credential-definition/repositories/credential-definition.repository.ts`:
- Around line 23-45: The saveCredentialDefinition method currently falls through
and returns undefined when getByAttribute finds an existing credential (causing
callers to get NPEs); update saveCredentialDefinition to explicitly handle the
duplicate case by returning the existing credential_definition (dbResult) or by
throwing a clear conflict error (e.g., ConflictError) instead of falling
through—locate saveCredentialDefinition and the getByAttribute call and either
add a return dbResult right after the dbResult check or throw a descriptive
error when dbResult is truthy so callers always receive a defined result or a
controlled exception.
- Around line 102-111: The getByAttribute method swallows errors by logging them
and returning undefined; update credential-definition.repository.ts so async
function getByAttribute(schema: string, tag: string) either re-throws the caught
error (throw error) or returns a rejected Promise after logging, ensuring
callers like saveCredentialDefinition can detect DB failures instead of treating
them as “not found”; specifically modify the catch block in getByAttribute to
include this re-throw behavior and preserve the original error context in the
logger call.
- Around line 171-196: The return type of getAgentType is incorrect: org_agents
is defined as a single optional relation but the method currently types it as an
array; update the Promise return type for getAgentType to reflect that it
returns organisation | null whose org_agents is either (org_agents & {
org_agent_type: org_agents_type }) or null (i.e., Promise<organisation & {
org_agents: (org_agents & { org_agent_type: org_agents_type }) | null } |
null>), and ensure the function signature and any callers/type assertions align
with this corrected type.

In `@apps/ledger/src/ledger.service.ts`:
- Around line 69-81: The null/empty check in schemaDetailsForEcosystem is wrong
because getSchemaDetails is always an object; replace the truthy check with a
check for emptiness (e.g., getSchemaDetails.schemasCount === 0 or
getSchemaDetails.schemasResult?.length === 0) and throw NotFoundException when
empty, and fix the copy-paste logger message by changing the error log from
"Error in getLedgerDetailsById" to "Error in schemaDetailsForEcosystem" (update
the this.logger.error call accordingly).
- Around line 18-31: The current check in getAllLedgers incorrectly treats an
empty array as falsy; update the logic in getAllLedgers to call
this.ledgerRepository.getAllLedgers(), then if the returned array has length ===
0 (e.g., getAllLedgerDetails.length === 0) throw the
NotFoundException(ResponseMessages.ledger.error.NotFound); otherwise return the
array; keep the catch block but ensure the thrown RpcException still forwards
the original error/response as before.

In `@apps/ledger/src/repositories/ledger.repository.ts`:
- Around line 15-22: The try/catch blocks in getAllLedgers, getNetworkUrl, and
getNetworkById are ineffective because the Prisma calls
(this.prisma.ledgers.findMany, this.prisma.networks.findFirst,
this.prisma.networks.findUnique) return Promises that are returned without
awaiting, so add await before each Prisma call so errors are thrown inside the
try block and caught by the existing this.logger.error/throw error handling;
ensure the methods remain async and keep the same log messages (e.g., in
getAllLedgers, getNetworkUrl, getNetworkById) so runtime exceptions are properly
logged and rethrown.

In `@apps/oid4vc-verification/src/oid4vc-verification.module.ts`:
- Line 52: The bootstrap in main.ts still imports/uses the old Oid4vpModule;
update the import statement to import Oid4vcVerificationModule and change the
Nest application creation to use Oid4vcVerificationModule (replace any remaining
Oid4vpModule references with Oid4vcVerificationModule) so the module class name
matches the renamed export.

In `@apps/organization/interfaces/organization.interface.ts`:
- Around line 1-2: Remove the fragile internal import of JsonValue and replace
its usage with the Prisma-provided type: delete the import "JsonValue" from
'libs/prisma-service/generated/prisma/internal/prismaNamespace' and change the
standalone JsonValue type reference (the usage at the position currently noted
on line 287) to Prisma.JsonValue; also remove the now-unused JsonValue import so
only the existing import { Prisma } from '@credebl/prisma/client' remains and
other references to Prisma.JsonValue (as seen elsewhere in the file) stay
consistent.

In `@apps/organization/repositories/organization.repository.ts`:
- Around line 508-521: The code assumes result from findFirst is non-null and
spreads it, which corrupts IGetOrgById when result === null; update the
getOrganization implementation to check "if (!result) return null;" before any
spreading or org_agents manipulation, keep transforming result.org_agents to an
array only when result exists, change the getOrganization return type to
Promise<IGetOrgById | null>, and audit callers of getOrganization to handle the
null case; references: findFirst, getOrganization, IGetOrgById, and org_agents.

In `@apps/user/repositories/fido-user.repository.ts`:
- Around line 112-118: Change the updateUserDetails signature to accept a single
UserUpdateData (not UserUpdateData[]): updateUserDetails(email: string,
additionalParams: UserUpdateData): Promise<user>; update the prisma update call
to spread additionalParams directly (data: { ...additionalParams }) and add a
guard/validation so additionalParams cannot be undefined before spreading; then
update the three call sites in the Fido service that currently pass a
single-element array to pass the object itself (remove the surrounding [ ... ]).
Ensure all types/imports reflect UserUpdateData (not array).

In `@libs/http-exception.filter.ts`:
- Line 3: Replace the incorrect internal import and fragile constructor-based
checks: change the import to "import { Prisma } from '@credebl/prisma/client';"
and in the error handling replace the switch(exception.constructor) logic with
instanceof checks using Prisma.PrismaClientKnownRequestError and
Prisma.PrismaClientValidationError (e.g., if (exception instanceof
Prisma.PrismaClientKnownRequestError) { ... } else if (exception instanceof
Prisma.PrismaClientValidationError) { ... }) to reliably detect Prisma errors at
runtime.

In `@libs/prisma-service/cli.ts`:
- Line 9: The require call in cli.ts is using a non-relative module specifier
and will fail at runtime; update the import for Prisma to use a relative path by
changing the require used to populate const { PrismaClient } to point to the
local generated client (use a ./ prefix like the other files do) so Node
resolves it from the package root rather than node_modules.

In `@libs/prisma-service/prisma/schema.prisma`:
- Line 612: The id fields on the credential_templates and x509_certificates
models are defined as String `@id` `@default`(uuid()) but are missing the `@db.Uuid`
attribute; update those fields to include `@db.Uuid` so the database column uses
PostgreSQL's native uuid type (e.g., change the credential_templates.id and
x509_certificates.id declarations to String `@id` `@default`(uuid()) `@db.Uuid`) to
make them consistent with other UUID primary keys and efficient for
indexing/joins.

In `@libs/prisma-service/prisma/seed.ts`:
- Around line 15-16: The code in seed.ts uses process.env.POOL_DATABASE_URL
directly causing a crash if unset; change the connectionString assignment to
fall back to process.env.DATABASE_URL (same behavior as cli.ts) and add a guard
that throws a clear error if neither is present before instantiating new
PrismaPg({ connectionString }); specifically update the connectionString
variable lookup and ensure the PrismaPg adapter creation is only attempted after
verifying connectionString is non-empty.

In `@libs/prisma-service/src/prisma-service.service.ts`:
- Around line 14-15: The code reads process.env.POOL_DATABASE_URL into
connectionString and passes it to new PrismaPg without the fallback used in
cli.ts, so replace the direct read with the same fallback logic (use
process.env.POOL_DATABASE_URL || process.env.DATABASE_URL) when constructing
connectionString for PrismaPg and add a simple validation that throws or logs a
descriptive error if the resulting connectionString is still missing; update the
usage around the PrismaPg instantiation (the connectionString variable and the
new PrismaPg({ connectionString }) call) to use the fallback and validation.

In `@libs/user-org-roles/src/user-org-roles.service.ts`:
- Around line 52-54: The loop is calling
userOrgRoleRepository.createUserOrgRole(...) without awaiting the returned
Promise, causing fire-and-forget writes and unhandled rejections; fix by
awaiting the calls: either change the for-loop to await each createUserOrgRole
call (sequential) or map roleIdList to an array of Promises via
userOrgRoleRepository.createUserOrgRole(...) and await Promise.all(...)
(parallel), ensuring the surrounding function is async and propagates or handles
rejections.

In `@prisma.config.ts`:
- Line 11: Fix the typo in the inline comment that reads "direct DB string here
(directUrl from old primsa.schema file)" by changing "primsa" to "prisma" so it
reads "...(directUrl from old prisma.schema file)"; update the comment near the
direct DB string placeholder to correct the misspelling.

---

Outside diff comments:
In `@apps/oid4vc-issuance/src/oid4vc-issuance.service.ts`:
- Around line 200-201: The if condition in oid4vc-issuance.service.ts
incorrectly uses && and can throw when getIssuerDetails is nullish; update the
check in the block that throws NotFoundException (using
ResponseMessages.oidcIssuer.error.notFound) to use || so it short-circuits:
i.e., test if (!getIssuerDetails || !getIssuerDetails.publicIssuerId) before
throwing; adjust any related null-safe logic in the surrounding method (where
getIssuerDetails is used) to match this corrected guard.

In `@apps/user/repositories/user-device.repository.ts`:
- Around line 252-257: The method updateDeviceByCredentialId is declared to
return Promise<Prisma.BatchPayload> but calls this.prisma.$queryRaw with a
SELECT (user_devices rows), causing a type mismatch; change the return type to
match the actual result (e.g., Promise<user_devices[]> or an appropriate
DTO/array type) and update callers if needed, and ensure the query uses the
correct $queryRaw or $queryRawUnsafe signature on this.prisma.$queryRaw and
parameter interpolation for credentialId to avoid SQL injection or LIKE-pattern
issues.
- Around line 150-153: The LIKE pattern is currently embedded as a literal
string '%${credentialId}%' inside the tagged $queryRaw, which breaks
parameterization and risks SQL injection; update the query to supply the pattern
as a parameter by concatenating the percent wildcards to credentialId outside
the SQL string (e.g., pass ${`%${credentialId}%`} or use CONCAT/|| with
${credentialId}) so the binding stays parameterized—look for the
this.prisma.$queryRaw call using credentialId in user-device.repository.ts and
replace the '%${credentialId}%' usage with a parameterized pattern.

In `@package.json`:
- Around line 25-27: Remove the legacy Prisma seed entry from package.json:
delete the "prisma" object that contains "seed": "ts-node prisma/seed.ts" since
Prisma v7 no longer supports package.json seed configuration; rely on the
existing prisma.config.ts's migrations.seed instead to avoid confusion and
technical debt.

In `@tsconfig.json`:
- Around line 59-70: The tsconfig path mapping for the base alias
"@credebl/prisma" is stale (it points to "libs/prisma/src" which no longer
exists); either remove the "@credebl/prisma" entry from the "paths" block or
change its target to a valid location such as "libs/prisma-service/src" (to
match the existing "@credebl/prisma/*" wildcard), and ensure the change keeps
consistency with "@credebl/prisma/*" and "@credebl/prisma-service" mappings so
imports resolve correctly.

---

Nitpick comments:
In `@apps/api-gateway/src/authz/authz.service.ts`:
- Around line 18-22: The imports from "@credebl/prisma/client" are split;
consolidate them into a single import and mark type-only imports with "import
type" to avoid runtime inclusion: replace the separate imports of "user" and
"Prisma" with one statement importing both as types (e.g., import type { user,
Prisma } from '@credebl/prisma/client') so references like the type annotation
for "user" on the method using IRestrictedUserSession/ISessionDetails are
correctly treated as type-only.

In `@apps/connection/src/connection.service.ts`:
- Around line 28-30: Consolidate the duplicate imports from
`@credebl/prisma/client` by merging the two import statements into one that
imports RecordType, user, and agent_invitations together; update the import
block in connection.service.ts to reference these symbols (RecordType, user,
agent_invitations) from a single import statement and remove the redundant
import so all Prisma types come from one line.

In `@apps/ledger/src/repositories/ledger.repository.ts`:
- Around line 59-109: Extract the duplicated Prisma filter into a local variable
inside handleGetSchemas and reuse it for both prisma.schema.findMany and
prisma.schema.count: create a const (e.g., schemasWhere) that contains the
schemaLedgerId/in array and the OR search clauses, then pass schemasWhere to the
where option of the findMany call that returns schemasResult and to the count
call that returns schemasCount so the filter logic is defined once and avoids
drift between the two queries.

In `@apps/ledger/src/schema/schema.controller.ts`:
- Around line 68-84: The method schemaExist has a long inline return type;
extract that object shape to a named interface (e.g., ISchemaExistResult) and
use ISchemaExistResult[] as the method's return type. Define the interface with
the same properties (id, createDateTime, createdBy, lastChangedDateTime,
lastChangedBy, name, version, attributes, schemaLedgerId, publisherDid,
issuerId, orgId, ledgerId) near other schema types (or export it from a shared
types file) and update schemaExist's signature to return
Promise<ISchemaExistResult[]>, keeping exports/visibility consistent with how
the file uses interfaces.

In `@apps/user/repositories/user-device.repository.ts`:
- Line 35: The repository uses defensive casts like String(userId) inside
UserDeviceRepository methods; remove those casts and pass the typed userId
through directly (replace String(userId) with userId) in all occurrences in
user-device.repository.ts, and instead add an explicit validation/assertion for
userId at the service boundary (e.g., in the UserDeviceService methods that call
the repository) to ensure userId is a string (or validate via DTO/schema) before
calling repository methods; update any related tests accordingly.

In `@libs/org-roles/repositories/index.ts`:
- Around line 15-40: Update error handling to be consistent and accurate: in
getRole and getOrgRoles replace the misleading new
InternalServerErrorException('Bad Request') with a proper
InternalServerErrorException containing contextual text (e.g., 'Failed
retrieving org roles' or 'Failed retrieving role') and include or preserve the
original error details in the log; ensure getOrgRolesByIds follows the same
pattern (log the error via this.logger.error with the error object/stringified
and then throw a standardized InternalServerErrorException) so all repository
methods (getRole, getOrgRoles, getOrgRolesByIds) uniformly log the original
error and throw a clear 500-level exception message.

In `@libs/prisma-service/prisma/schema.prisma`:
- Line 770: In the ecosystem_invitations model remove the stray blank line
between the user relation declaration (the line defining the relation field
`user`) and the model-level constraint `@@unique` so that the `user` relation
and the `@@unique` constraint are adjacent and match the formatting style used
by other models; edit the `ecosystem_invitations` model to delete that empty
line and ensure spacing matches other model blocks.

In `@libs/prisma-service/src/prisma-service.service.ts`:
- Around line 32-54: onModuleInit currently calls await this.$connect() before
registering Prisma event listeners ($on for 'error','warn','query'), which can
miss events emitted during connection; move the (this as any).$on(...)
registration blocks for 'error', 'warn', and 'query' to execute before calling
await this.$connect(), keeping the same handlers/signatures (Prisma.LogEvent,
Prisma.QueryEvent) and then call await this.$connect() so all connection-time
events are captured by the existing listeners.

Comment on lines +2 to +5
import { Prisma, PrismaClient } from '@credebl/prisma/client';

import { CommonTableColumns } from '@credebl/common/interfaces/interface';
import { JsonValue } from '@prisma/client/runtime/library';
import { JsonValue } from '@credebl/prisma/internal/prismaNamespace';
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:

rg -n "JsonValue" --type=ts -C2

Repository: credebl/platform

Length of output: 11733


🏁 Script executed:

fd "prismaNamespace" --type f

Repository: credebl/platform

Length of output: 42


🏁 Script executed:

find . -type f -name "*.ts" | xargs grep -l "@credebl/prisma" | head -20

Repository: credebl/platform

Length of output: 1478


🌐 Web query:

Prisma v7 JsonValue import source

💡 Result:

In Prisma v7, JsonValue comes from the Prisma namespace in @prisma/client:

import type { Prisma } from '@prisma/client';

type X = Prisma.JsonValue;

This is the documented/public pattern for JSON helper types like Prisma.JsonArray / Prisma.JsonObject / Prisma.JsonValue. [1] (Example usage: import { Prisma } from "@prisma/client" then Prisma.JsonValue.) [2]

If you specifically want a direct type import, some projects import it from:

import type { JsonValue } from '@prisma/client/runtime/library';

…but Prisma considers @prisma/client/runtime/* a private API (no backward-compat guarantees). [3] [4]

Sources: [1] [2] [3] [4]


Replace the custom JsonValue import with the standard Prisma pattern.

The import from @credebl/prisma/internal/prismaNamespace is non-standard and inconsistent with how JsonValue is used throughout the codebase. Prisma v7 exposes JsonValue via the Prisma namespace, which you already import on line 2. Use Prisma.JsonValue instead:

// Current (line 5)
import { JsonValue } from '@credebl/prisma/internal/prismaNamespace';

// Replace with usage of existing Prisma import
// Then use: Prisma.JsonValue in the interface (line 182)

This aligns with the standard pattern used in 15+ other files across the codebase (e.g., apps/user/repositories/user-device.repository.ts, apps/agent-service/src/interface/agent-service.interface.ts).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ecosystem/interfaces/ecosystem.interfaces.ts` around lines 2 - 5, Remove
the non-standard import of JsonValue from
'@credebl/prisma/internal/prismaNamespace' and replace all uses of the
standalone JsonValue type with Prisma.JsonValue, leveraging the already-imported
Prisma symbol (import { Prisma, PrismaClient } ...). Update any interface/type
declarations that reference JsonValue to use Prisma.JsonValue so the file
follows the standard Prisma v7 pattern used elsewhere.

Comment on lines +23 to +45
async saveCredentialDefinition(credDef: CredDefPayload): Promise<credential_definition> {
try {
const dbResult: credential_definition = await this.getByAttribute(credDef.schemaLedgerId, credDef.tag);
if (!dbResult) {
const saveResult = await this.prisma.credential_definition.create({
data: {
schemaLedgerId: credDef.schemaLedgerId,
tag: credDef.tag,
credentialDefinitionId: credDef.credentialDefinitionId,
revocable: credDef.revocable,
createdBy: credDef.createdBy,
lastChangedBy: credDef.lastChangedBy,
orgId: credDef.orgId,
schemaId: credDef.schemaId
}
});
return saveResult;
}
} catch (error) {
this.logger.error(`${ResponseMessages.credentialDefinition.error.NotSaved}: ${error.message} `);
throw error;
}
}
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

saveCredentialDefinition silently returns undefined when a duplicate exists.

If getByAttribute finds an existing record, execution falls through the if (!dbResult) block with no return value. Callers that expect a credential_definition object will receive undefined, which can cause downstream NPEs.

Consider explicitly returning the existing record or throwing a conflict error:

Proposed fix
   async saveCredentialDefinition(credDef: CredDefPayload): Promise<credential_definition> {
     try {
       const dbResult: credential_definition = await this.getByAttribute(credDef.schemaLedgerId, credDef.tag);
       if (!dbResult) {
         const saveResult = await this.prisma.credential_definition.create({
           ...
         });
         return saveResult;
       }
+      return dbResult;
     } catch (error) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async saveCredentialDefinition(credDef: CredDefPayload): Promise<credential_definition> {
try {
const dbResult: credential_definition = await this.getByAttribute(credDef.schemaLedgerId, credDef.tag);
if (!dbResult) {
const saveResult = await this.prisma.credential_definition.create({
data: {
schemaLedgerId: credDef.schemaLedgerId,
tag: credDef.tag,
credentialDefinitionId: credDef.credentialDefinitionId,
revocable: credDef.revocable,
createdBy: credDef.createdBy,
lastChangedBy: credDef.lastChangedBy,
orgId: credDef.orgId,
schemaId: credDef.schemaId
}
});
return saveResult;
}
} catch (error) {
this.logger.error(`${ResponseMessages.credentialDefinition.error.NotSaved}: ${error.message} `);
throw error;
}
}
async saveCredentialDefinition(credDef: CredDefPayload): Promise<credential_definition> {
try {
const dbResult: credential_definition = await this.getByAttribute(credDef.schemaLedgerId, credDef.tag);
if (!dbResult) {
const saveResult = await this.prisma.credential_definition.create({
data: {
schemaLedgerId: credDef.schemaLedgerId,
tag: credDef.tag,
credentialDefinitionId: credDef.credentialDefinitionId,
revocable: credDef.revocable,
createdBy: credDef.createdBy,
lastChangedBy: credDef.lastChangedBy,
orgId: credDef.orgId,
schemaId: credDef.schemaId
}
});
return saveResult;
}
return dbResult;
} catch (error) {
this.logger.error(`${ResponseMessages.credentialDefinition.error.NotSaved}: ${error.message} `);
throw error;
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/ledger/src/credential-definition/repositories/credential-definition.repository.ts`
around lines 23 - 45, The saveCredentialDefinition method currently falls
through and returns undefined when getByAttribute finds an existing credential
(causing callers to get NPEs); update saveCredentialDefinition to explicitly
handle the duplicate case by returning the existing credential_definition
(dbResult) or by throwing a clear conflict error (e.g., ConflictError) instead
of falling through—locate saveCredentialDefinition and the getByAttribute call
and either add a return dbResult right after the dbResult check or throw a
descriptive error when dbResult is truthy so callers always receive a defined
result or a controlled exception.

Comment on lines +102 to +111
async getByAttribute(schema: string, tag: string): Promise<credential_definition> {
try {
const response = await this.prisma.credential_definition.findFirst({
where: { schemaLedgerId: schema, tag: { contains: tag, mode: 'insensitive' } }
});
return response;
} catch (error) {
this.logger.error(`${ResponseMessages.credentialDefinition.error.NotFound}: ${error}`);
}
}
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

getByAttribute swallows errors — catch block doesn't re-throw.

The catch block logs the error but doesn't throw, so any Prisma query failure silently returns undefined. This masks database errors and makes saveCredentialDefinition (which depends on this method) believe no existing record was found, potentially leading to duplicate creation attempts or constraint violations.

Proposed fix
     } catch (error) {
       this.logger.error(`${ResponseMessages.credentialDefinition.error.NotFound}: ${error}`);
+      throw error;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async getByAttribute(schema: string, tag: string): Promise<credential_definition> {
try {
const response = await this.prisma.credential_definition.findFirst({
where: { schemaLedgerId: schema, tag: { contains: tag, mode: 'insensitive' } }
});
return response;
} catch (error) {
this.logger.error(`${ResponseMessages.credentialDefinition.error.NotFound}: ${error}`);
}
}
async getByAttribute(schema: string, tag: string): Promise<credential_definition> {
try {
const response = await this.prisma.credential_definition.findFirst({
where: { schemaLedgerId: schema, tag: { contains: tag, mode: 'insensitive' } }
});
return response;
} catch (error) {
this.logger.error(`${ResponseMessages.credentialDefinition.error.NotFound}: ${error}`);
throw error;
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/ledger/src/credential-definition/repositories/credential-definition.repository.ts`
around lines 102 - 111, The getByAttribute method swallows errors by logging
them and returning undefined; update credential-definition.repository.ts so
async function getByAttribute(schema: string, tag: string) either re-throws the
caught error (throw error) or returns a rejected Promise after logging, ensuring
callers like saveCredentialDefinition can detect DB failures instead of treating
them as “not found”; specifically modify the catch block in getByAttribute to
include this re-throw behavior and preserve the original error context in the
logger call.

Comment on lines +171 to +196
async getAgentType(orgId: string): Promise<
organisation & {
org_agents: (org_agents & {
org_agent_type: org_agents_type;
})[];
}
> {
try {
const agentDetails = await this.prisma.organisation.findUnique({
where: {
id: orgId
},
include: {
org_agents: {
include: {
org_agent_type: true
}
}
}
});
return agentDetails;
} catch (error) {
this.logger.error(`Error in getting agent type: ${error}`);
throw error;
}
}
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:

fd "schema.prisma" --type f

Repository: credebl/platform

Length of output: 100


🏁 Script executed:

cat libs/prisma-service/prisma/schema.prisma | grep -B5 -A10 "model org_agents"

Repository: credebl/platform

Length of output: 1362


🏁 Script executed:

cat libs/prisma-service/prisma/schema.prisma | grep -B2 -A20 "^model organisation"

Repository: credebl/platform

Length of output: 1238


🏁 Script executed:

cat libs/prisma-service/prisma/schema.prisma | grep -A100 "^model organisation" | grep -B2 -A2 "org_agents"

Repository: credebl/platform

Length of output: 508


Fix return type of getAgentTypeorg_agents is a single optional object, not an array.

The Prisma schema defines org_agents as org_agents? (single optional relation), but the return type annotates it as an array: org_agents[]. Since the query uses findUnique with a single org_agents include, Prisma returns a single object or null, not an array. Update the return type to reflect this:

Promise<
  organisation & {
    org_agents: (org_agents & {
      org_agent_type: org_agents_type;
    }) | null;
  } | null
>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/ledger/src/credential-definition/repositories/credential-definition.repository.ts`
around lines 171 - 196, The return type of getAgentType is incorrect: org_agents
is defined as a single optional relation but the method currently types it as an
array; update the Promise return type for getAgentType to reflect that it
returns organisation | null whose org_agents is either (org_agents & {
org_agent_type: org_agents_type }) or null (i.e., Promise<organisation & {
org_agents: (org_agents & { org_agent_type: org_agents_type }) | null } |
null>), and ensure the function signature and any callers/type assertions align
with this corrected type.

Comment on lines +18 to +31
async getAllLedgers(): Promise<ledgers[]> {
try {
const getAllLedgerDetails = await this.ledgerRepository.getAllLedgers();

if (!getAllLedgerDetails) {
throw new NotFoundException(ResponseMessages.ledger.error.NotFound);
}

return getAllLedgerDetails;
} catch (error) {
this.logger.error(`Error in retrieving all ledgers: ${error}`);
throw new RpcException(error.response ? error.response : error);
}
}
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

!getAllLedgerDetails will never be falsy — findMany returns [], not null.

Prisma's findMany always returns an array (empty if no results). The check !getAllLedgerDetails on line 22 will never trigger because an empty array is truthy. If the intent is to throw when no ledgers exist, check the array length instead.

🐛 Proposed fix
-      if (!getAllLedgerDetails) {
+      if (0 === getAllLedgerDetails.length) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async getAllLedgers(): Promise<ledgers[]> {
try {
const getAllLedgerDetails = await this.ledgerRepository.getAllLedgers();
if (!getAllLedgerDetails) {
throw new NotFoundException(ResponseMessages.ledger.error.NotFound);
}
return getAllLedgerDetails;
} catch (error) {
this.logger.error(`Error in retrieving all ledgers: ${error}`);
throw new RpcException(error.response ? error.response : error);
}
}
async getAllLedgers(): Promise<ledgers[]> {
try {
const getAllLedgerDetails = await this.ledgerRepository.getAllLedgers();
if (0 === getAllLedgerDetails.length) {
throw new NotFoundException(ResponseMessages.ledger.error.NotFound);
}
return getAllLedgerDetails;
} catch (error) {
this.logger.error(`Error in retrieving all ledgers: ${error}`);
throw new RpcException(error.response ? error.response : error);
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ledger/src/ledger.service.ts` around lines 18 - 31, The current check in
getAllLedgers incorrectly treats an empty array as falsy; update the logic in
getAllLedgers to call this.ledgerRepository.getAllLedgers(), then if the
returned array has length === 0 (e.g., getAllLedgerDetails.length === 0) throw
the NotFoundException(ResponseMessages.ledger.error.NotFound); otherwise return
the array; keep the catch block but ensure the thrown RpcException still
forwards the original error/response as before.


model credential_templates {
id String @id @default(uuid())
id String @id @default(uuid())
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 @db.Uuid on credential_templates.id and x509_certificates.id.

Nearly every other UUID primary key in this schema uses @db.Uuid to store the value as a native PostgreSQL uuid type. These two models use @id @default(uuid()) without @db.Uuid, which means the column will be stored as text — inconsistent with the rest of the schema and less efficient for indexing/joins.

🐛 Proposed fix
 model credential_templates {
-  id           String       `@id` `@default`(uuid())
+  id           String       `@id` `@default`(uuid()) `@db.Uuid`
   name         String
 model x509_certificates {
-  id                  String     `@id` `@default`(uuid())
+  id                  String     `@id` `@default`(uuid()) `@db.Uuid`
   orgAgentId          String     `@db.Uuid`

Also applies to: 627-627

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/prisma-service/prisma/schema.prisma` at line 612, The id fields on the
credential_templates and x509_certificates models are defined as String `@id`
`@default`(uuid()) but are missing the `@db.Uuid` attribute; update those fields to
include `@db.Uuid` so the database column uses PostgreSQL's native uuid type
(e.g., change the credential_templates.id and x509_certificates.id declarations
to String `@id` `@default`(uuid()) `@db.Uuid`) to make them consistent with other UUID
primary keys and efficient for indexing/joins.

Comment on lines +15 to +16
const connectionString = process.env.POOL_DATABASE_URL as string;
const adapter = new PrismaPg({ connectionString });
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 fallback for POOL_DATABASE_URL — same issue as in prisma-service.service.ts.

Unlike cli.ts which falls back to DATABASE_URL, this file will fail with an opaque error if POOL_DATABASE_URL is unset. Consider adding a fallback and/or a guard, consistent with cli.ts line 13.

Suggested fix
-const connectionString = process.env.POOL_DATABASE_URL as string;
+const connectionString = (process.env.POOL_DATABASE_URL || process.env.DATABASE_URL) as string;
+if (!connectionString) {
+  throw new Error('Neither POOL_DATABASE_URL nor DATABASE_URL is set');
+}
 const adapter = new PrismaPg({ connectionString });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const connectionString = process.env.POOL_DATABASE_URL as string;
const adapter = new PrismaPg({ connectionString });
const connectionString = (process.env.POOL_DATABASE_URL || process.env.DATABASE_URL) as string;
if (!connectionString) {
throw new Error('Neither POOL_DATABASE_URL nor DATABASE_URL is set');
}
const adapter = new PrismaPg({ connectionString });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/prisma-service/prisma/seed.ts` around lines 15 - 16, The code in seed.ts
uses process.env.POOL_DATABASE_URL directly causing a crash if unset; change the
connectionString assignment to fall back to process.env.DATABASE_URL (same
behavior as cli.ts) and add a guard that throws a clear error if neither is
present before instantiating new PrismaPg({ connectionString }); specifically
update the connectionString variable lookup and ensure the PrismaPg adapter
creation is only attempted after verifying connectionString is non-empty.

Comment on lines +14 to +15
const connectionString = process.env.POOL_DATABASE_URL as string;
const adapter = new PrismaPg({ connectionString });
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 fallback for POOL_DATABASE_URL — inconsistent with cli.ts.

cli.ts (line 13) uses process.env.POOL_DATABASE_URL || process.env.DATABASE_URL as a fallback, but here POOL_DATABASE_URL is read without any fallback. If the variable is unset, connectionString will be undefined (cast away by as string), and PrismaPg will throw an opaque error at runtime.

Suggested fix
-    const connectionString = process.env.POOL_DATABASE_URL as string;
-    const adapter = new PrismaPg({ connectionString });
+    const connectionString = process.env.POOL_DATABASE_URL || process.env.DATABASE_URL;
+    if (!connectionString) {
+      throw new Error('Neither POOL_DATABASE_URL nor DATABASE_URL is set');
+    }
+    const adapter = new PrismaPg({ connectionString });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const connectionString = process.env.POOL_DATABASE_URL as string;
const adapter = new PrismaPg({ connectionString });
const connectionString = process.env.POOL_DATABASE_URL || process.env.DATABASE_URL;
if (!connectionString) {
throw new Error('Neither POOL_DATABASE_URL nor DATABASE_URL is set');
}
const adapter = new PrismaPg({ connectionString });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/prisma-service/src/prisma-service.service.ts` around lines 14 - 15, The
code reads process.env.POOL_DATABASE_URL into connectionString and passes it to
new PrismaPg without the fallback used in cli.ts, so replace the direct read
with the same fallback logic (use process.env.POOL_DATABASE_URL ||
process.env.DATABASE_URL) when constructing connectionString for PrismaPg and
add a simple validation that throws or logs a descriptive error if the resulting
connectionString is still missing; update the usage around the PrismaPg
instantiation (the connectionString variable and the new PrismaPg({
connectionString }) call) to use the fallback and validation.

Comment on lines 52 to 54
for (const roleData of roleIdList) {
this.userOrgRoleRepository.createUserOrgRole(userId, roleData.roleId, orgId, roleData.idpRoleId);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Missing await on async repository call — promises are fire-and-forget.

createUserOrgRole returns a Promise, but the call is not awaited. This means:

  1. The function returns true before any DB writes complete.
  2. Rejected promises are silently swallowed (unhandled rejection).
  3. Callers cannot rely on the return value to confirm roles were actually created.
🐛 Proposed fix
     for (const roleData of roleIdList) {
-      this.userOrgRoleRepository.createUserOrgRole(userId, roleData.roleId, orgId, roleData.idpRoleId);
+      await this.userOrgRoleRepository.createUserOrgRole(userId, roleData.roleId, orgId, roleData.idpRoleId);
     }

If the writes are independent and you want parallelism:

-    for (const roleData of roleIdList) {
-      this.userOrgRoleRepository.createUserOrgRole(userId, roleData.roleId, orgId, roleData.idpRoleId);
-    }
+    await Promise.all(
+      roleIdList.map((roleData) =>
+        this.userOrgRoleRepository.createUserOrgRole(userId, roleData.roleId, orgId, roleData.idpRoleId)
+      )
+    );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const roleData of roleIdList) {
this.userOrgRoleRepository.createUserOrgRole(userId, roleData.roleId, orgId, roleData.idpRoleId);
}
for (const roleData of roleIdList) {
await this.userOrgRoleRepository.createUserOrgRole(userId, roleData.roleId, orgId, roleData.idpRoleId);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/user-org-roles/src/user-org-roles.service.ts` around lines 52 - 54, The
loop is calling userOrgRoleRepository.createUserOrgRole(...) without awaiting
the returned Promise, causing fire-and-forget writes and unhandled rejections;
fix by awaiting the calls: either change the for-loop to await each
createUserOrgRole call (sequential) or map roleIdList to an array of Promises
via userOrgRoleRepository.createUserOrgRole(...) and await Promise.all(...)
(parallel), ensuring the surrounding function is async and propagates or handles
rejections.

seed: 'ts-node libs/prisma-service/prisma/seed.ts'
},
datasource: {
// direct DB string here (directUrl from old primsa.schema 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 | 🟡 Minor

Typo in comment: "primsa" → "prisma".

-    // direct DB string here (directUrl from old primsa.schema file)
+    // direct DB string here (directUrl from old prisma.schema file)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// direct DB string here (directUrl from old primsa.schema file)
// direct DB string here (directUrl from old prisma.schema file)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@prisma.config.ts` at line 11, Fix the typo in the inline comment that reads
"direct DB string here (directUrl from old primsa.schema file)" by changing
"primsa" to "prisma" so it reads "...(directUrl from old prisma.schema file)";
update the comment near the direct DB string placeholder to correct the
misspelling.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants