Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 57 additions & 7 deletions apps/api-gateway/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import * as dotenv from 'dotenv';
import * as express from 'express';

import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

Check warning on line 5 in apps/api-gateway/src/main.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'@nestjs/swagger' imported multiple times.

See more on https://sonarcloud.io/project/issues?id=credebl_platform&issues=AZ3JnRQq75J5TtH9ERUc&open=AZ3JnRQq75J5TtH9ERUc&pullRequest=1608
import { OpenAPIObject } from '@nestjs/swagger';

Check warning on line 6 in apps/api-gateway/src/main.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'@nestjs/swagger' imported multiple times.

See more on https://sonarcloud.io/project/issues?id=credebl_platform&issues=AZ3JnRQq75J5TtH9ERUd&open=AZ3JnRQq75J5TtH9ERUd&pullRequest=1608
import { Logger, VERSION_NEUTRAL, VersioningType } from '@nestjs/common';
import * as cookieParser from 'cookie-parser';
import { AppModule } from './app.module';
Expand Down Expand Up @@ -88,15 +89,64 @@
});

// Create Swagger document
let document = SwaggerModule.createDocument(app, options);
try {
const ecosystemFilter = app.get(EcosystemSwaggerFilter);
document = await ecosystemFilter.filterDocument(document);
} catch (err) {
Logger.warn('Skipping EcosystemSwaggerFilter due to error', err as Error);
let document = SwaggerModule.createDocument(app, options);
try {
const ecosystemFilter = app.get(EcosystemSwaggerFilter);
document = await ecosystemFilter.filterDocument(document);
} catch (err) {
Logger.warn('Skipping EcosystemSwaggerFilter due to error', err as Error);
}

// 🔹 Helper to filter APIs by tag


function filterByTags(doc: OpenAPIObject, tagNames: string[]): OpenAPIObject {

Check warning on line 103 in apps/api-gateway/src/main.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Move function 'filterByTags' to the outer scope.

See more on https://sonarcloud.io/project/issues?id=credebl_platform&issues=AZ3JnRQq75J5TtH9ERUe&open=AZ3JnRQq75J5TtH9ERUe&pullRequest=1608
const filteredPaths: OpenAPIObject['paths'] = {};

for (const [path, methods] of Object.entries(doc.paths)) {
for (const [method, operation] of Object.entries(methods)) {
if (
operation.tags &&
operation.tags.some((tag: string) => tagNames.includes(tag))

Check warning on line 110 in apps/api-gateway/src/main.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=credebl_platform&issues=AZ3Id2m6YWOgUukHg3-o&open=AZ3Id2m6YWOgUukHg3-o&pullRequest=1608
) {
if (!filteredPaths[path]) {
filteredPaths[path] = {};
}
filteredPaths[path][method] = operation;
}
}
}

SwaggerModule.setup('api', app, document);
return {
...doc,
paths: filteredPaths
};
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
// 🔹 Create separate documents
const didcommDoc = filterByTags(document, [
'connections',
'verifications'
]);

const oid4vcDoc = filterByTags(document, [
'OID4VC',
'OID4VP'
]);

const utilsDoc = filterByTags(document, [
'utilities',
'ledgers',
'webhooks',
'geolocation',
'notification'
]);
Comment on lines +126 to +142
Copy link
Copy Markdown

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
# Enumerate all distinct `@ApiTags` values to verify the literals used in main.ts.
echo "=== Distinct `@ApiTags` values across the repo ==="
rg -nP "@ApiTags\(\s*['\"\`]([^'\"\`]+)['\"\`]" -r '$1' --type=ts -o --no-filename \
  | sort -u

echo
echo "=== Issuance-related controllers & their tags ==="
rg -nP --type=ts -C2 "@ApiTags\([^)]*[Ii]ssuance[^)]*\)"

echo
echo "=== Notification controller(s) & their tags ==="
fd -t f -e ts notification | xargs -I{} rg -nP "@ApiTags\(" {} 2>/dev/null

Repository: credebl/platform

Length of output: 789


🏁 Script executed:

# Find the credentials controller and see what endpoints it covers
rg -l "@ApiTags\('credentials'\)" --type=ts

# Also check the context around the credentials tag
rg -B5 -A20 "@ApiTags\('credentials'\)" --type=ts | head -80

Repository: credebl/platform

Length of output: 2580


🏁 Script executed:

# Show the exact lines in main.ts around the didcommDoc filter
sed -n '125,141p' apps/api-gateway/src/main.ts

Repository: credebl/platform

Length of output: 337


Add 'credentials' tag to didcommDoc filter.

The credentials controller (issuance endpoints) uses @ApiTags('credentials'), not 'issuance'. Credential issuance is a core DIDComm capability, yet the didcommDoc filter currently only covers 'connections' and 'verifications'. The 'credentials' tag must be included so that issuance endpoints appear under /api/didcomm.

The 'notification' tag is correctly singular and matches the actual controller tag.

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

In `@apps/api-gateway/src/main.ts` around lines 125 - 141, Update the didcommDoc
filter to include the 'credentials' tag so the issuance controller endpoints
(tagged with `@ApiTags`('credentials')) are included under didcomm routes: modify
the array passed to filterByTags for the didcommDoc constant (where didcommDoc
is defined) to add 'credentials' alongside 'connections' and 'verifications',
leaving other filters (e.g., utilsDoc and oid4vcDoc) unchanged.

// 🔹 Default full Swagger
SwaggerModule.setup('api', app, document);

// 🔹 New grouped Swagger UIs
SwaggerModule.setup('api/didcomm', app, didcommDoc);
SwaggerModule.setup('api/oid4vc', app, oid4vcDoc);
SwaggerModule.setup('api/utils', app, utilsDoc);
const httpAdapter: HttpAdapterHost = app.get(HttpAdapterHost) as HttpAdapterHost;
app.useGlobalFilters(new AllExceptionsFilter(httpAdapter));
const { ENABLE_CORS_IP_LIST } = process.env || {};
Expand Down