docs: move additional exploration docs to docs/audits/

Move 6 recently generated inquiry and MCP exploration documents
to the centralized audit directory.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-11 01:41:23 +07:00
parent 4372a9ee12
commit 25b22ea9bd
6 changed files with 2116 additions and 0 deletions

View File

@@ -0,0 +1,396 @@
================================================================================
MCP MODULE - COMPLETE FILES LISTING
================================================================================
PROJECT: GoodGo Platform
MODULE: Model Context Protocol (MCP) Integration
LOCATION: apps/api/src/modules/mcp/
DATE: April 11, 2026
================================================================================
1. SOURCE FILES
================================================================================
📄 File 1: apps/api/src/modules/mcp/index.ts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Type: Module Export/Index
Lines: 1
Purpose: Main module entry point
Exports: { McpIntegrationModule }
Content:
────────
export { McpIntegrationModule } from './mcp.module';
Status: ✅ Simple re-export, well-formed
📄 File 2: apps/api/src/modules/mcp/mcp.module.ts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Type: NestJS Module Configuration
Lines: 22
Purpose: Bootstrap MCP integration module with dependencies
Key Features:
• @Module decorator with imports, controllers
• Implements OnModuleInit lifecycle hook
• Configures McpCoreModule.forRoot() with settings
• Sets up service integration (Typesense, Auth, MCP Registry)
• Logs initialized servers on startup
Decorator: @Module({
imports: [SearchModule, AuthModule, McpCoreModule.forRoot({...})],
controllers: [McpTransportController],
})
Class: McpIntegrationModule implements OnModuleInit
Injected Dependencies:
1. typesenseClient: TypesenseClientService (from SearchModule)
2. mcpRegistry: McpRegistryService (from @goodgo/mcp-servers)
3. logger: LoggerService (from SharedModule)
Lifecycle Hook:
async onModuleInit(): Promise<void>
- Sets Typesense client on registry
- Re-initializes MCP servers
- Logs server names on startup
Status: ⚠️ Partially tested (initialization logic not covered)
📄 File 3: apps/api/src/modules/mcp/presentation/mcp-transport.controller.ts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Type: NestJS HTTP Controller
Lines: 102
Purpose: HTTP transport layer for MCP Server-Sent Events (SSE) connections
Decorators Applied:
@ApiTags('mcp') - Swagger grouping
@ApiBearerAuth('JWT') - API doc
@Controller('mcp') - Route prefix
@UseGuards(JwtAuthGuard) - Auth guard (all endpoints)
Private Properties:
transports: Map<string, SSEServerTransport>
→ Active session tracking by sessionId
Constructor:
McpTransportController(registry: McpRegistryService)
Endpoints (3):
1⃣ GET /mcp/servers
├── Decorator: @Get('servers')
├── Throttle: 30 requests per 60,000ms
├── Auth: JwtAuthGuard ✅
├── Returns: { servers: string[] }
├── HTTP Status: 200 OK, 401 Unauthorized
└── Logic: Returns server.names from registry
2⃣ GET /mcp/:serverName/sse
├── Decorator: @Get(':serverName/sse')
├── Throttle: 5 requests per 60,000ms ⚡ (STRICTER)
├── Params: serverName (string)
├── Auth: JwtAuthGuard ✅, CurrentUser decorator
├── Returns: SSE stream (response.write)
├── HTTP Status: 200 (stream), 404 (not found), 401 (unauthorized)
└── Logic:
1. Verify server exists (throw NOT_FOUND if not)
2. Create SSEServerTransport instance
3. Store in Map[sessionId]
4. Attach close listener for cleanup
5. Connect transport to server
3⃣ POST /mcp/:serverName/messages
├── Decorator: @Post(':serverName/messages')
├── Throttle: 30 requests per 60,000ms
├── Params: serverName (string)
├── Query: sessionId (required)
├── Auth: JwtAuthGuard ✅, CurrentUser decorator
├── Returns: Delegate response to transport
├── HTTP Status: 200 OK, 400 (missing sessionId), 404 (not found), 401 (unauthorized)
└── Logic:
1. Extract sessionId from query
2. Validate sessionId present (throw BAD_REQUEST if not)
3. Look up transport (throw NOT_FOUND if expired)
4. Delegate to transport.handlePostMessage()
Status: ✅ Well tested (see spec file)
================================================================================
2. TEST FILES
================================================================================
🧪 File 4: apps/api/src/modules/mcp/presentation/__tests__/mcp-transport.controller.spec.ts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Type: Unit Test Suite
Lines: 174
Testing Framework: Vitest
Subject: McpTransportController
Test Coverage: 11 tests in 4 describe blocks
DESCRIBE BLOCK 1: security decorators (4 tests)
────────────────────────────────────────────────
✅ Test 1: has JwtAuthGuard applied at controller level
Method: Reflect.getMetadata('__guards__', McpTransportController)
Checks: guards exist and contain JwtAuthGuard
✅ Test 2: has Throttle metadata on listServers endpoint
Metadata: THROTTLER:LIMITdefault
Expected: 30
✅ Test 3: has Throttle metadata on handleSse endpoint with low limit
Metadata: THROTTLER:LIMITdefault on handleSse
Expected: 5 (stricter limit)
✅ Test 4: has Throttle metadata on handleMessage endpoint
Metadata: THROTTLER:LIMITdefault
Expected: 30
DESCRIBE BLOCK 2: listServers (2 tests)
────────────────────────────────────────
✅ Test 1: returns list of server names from registry
Setup: mockRegistry.getServerNames.mockReturnValue(['search', 'listings'])
Action: controller.listServers()
Assert: result.servers equals ['search', 'listings']
Verify: getServerNames called once
✅ Test 2: returns empty array when no servers registered
Setup: mockRegistry.getServerNames.mockReturnValue([])
Action: controller.listServers()
Assert: result.servers equals []
DESCRIBE BLOCK 3: handleSse (3 tests)
──────────────────────────────────────
✅ Test 1: throws NOT_FOUND when server does not exist
Setup: mockRegistry.getServer.mockReturnValue(null)
Action: controller.handleSse('nonexistent', mockUser, req, res)
Assert: Throws HttpException
Status: HttpStatus.NOT_FOUND
Message: Contains 'nonexistent'
✅ Test 2: creates transport and connects to server
Setup: mockServer.connect mock resolved
Action: controller.handleSse('search', mockUser, req, res)
Verify:
- getServer called with 'search'
- connect called once
- req.on called with 'close' event
✅ Test 3: cleans up transport on connection close
Setup: handleSse called successfully
Action: Simulate connection close by calling closeHandler
Assert: Subsequent handleMessage fails with NOT_FOUND
(proves transport was deleted from Map)
DESCRIBE BLOCK 4: handleMessage (2 tests)
──────────────────────────────────────────
✅ Test 1: throws BAD_REQUEST when sessionId query parameter is missing
Setup: mockReq.query = {}
Action: controller.handleMessage('search', mockUser, req, res)
Assert: Throws HttpException
Status: HttpStatus.BAD_REQUEST
✅ Test 2: throws NOT_FOUND when session does not exist
Setup: mockReq.query = { sessionId: 'nonexistent-session' }
Action: controller.handleMessage('search', mockUser, req, res)
Assert: Throws HttpException
Status: HttpStatus.NOT_FOUND
Mocking Strategies Used:
1. vi.mock() - Module mocking (SSEServerTransport)
2. vi.fn() - Function mocks (service methods)
3. mockReturnValue() - Sync returns
4. mockResolvedValue() - Async returns
5. Manual mock objects - req/res simulation
6. Reflect.getMetadata() - Decorator inspection
Status: ✅ Comprehensive test coverage
================================================================================
3. ARCHITECTURE & DDD LAYERS
================================================================================
Current Status: SIMPLIFIED ARCHITECTURE (Presentation-only)
✅ IMPLEMENTED LAYERS:
Presentation Layer
├── Controllers
│ └── mcp-transport.controller.ts (102 lines)
│ ├── 3 HTTP endpoints
│ ├── JWT auth protection
│ ├── Rate limiting (throttle)
│ └── SSE session management
└── Tests
└── __tests__/mcp-transport.controller.spec.ts (174 lines)
├── 11 tests
├── 4 describe blocks
└── Comprehensive coverage
❌ MISSING LAYERS:
Domain Layer (NO FILES)
├── No entities/
├── No value-objects/
├── No domain-events/
└── No repositories/ interfaces
Application Layer (NO FILES)
├── No handlers/ (CQRS)
├── No commands/
├── No queries/
└── No DTOs/
Infrastructure Layer (NO FILES)
├── No repositories/ (implementations)
├── No services/
└── No external-adapters/
Architecture Notes:
• Acts as integration wrapper
• Delegates to @goodgo/mcp-servers library
• Simple HTTP-to-SSE bridge
• In-memory session tracking (Map)
• No persistence or business logic
================================================================================
4. DEPENDENCIES & IMPORTS
================================================================================
External Dependencies:
• @goodgo/mcp-servers (SSEServerTransport, McpRegistryService)
• @nestjs/common (Controller, decorators, etc.)
• @nestjs/swagger (API documentation)
• @nestjs/throttler (Rate limiting)
Internal Dependencies:
• @modules/auth (JwtAuthGuard, CurrentUser)
• @modules/search (TypesenseClientService)
• @modules/shared (LoggerService)
Direct Imports in Module:
import { McpTransportController } from './presentation/mcp-transport.controller';
import { SearchModule, AuthModule } from other modules;
================================================================================
5. KEY STATISTICS
================================================================================
File Count:
• Total Source Files: 4
• Test Files: 1
• Lines of Code: 125 (implementation only)
• Lines of Tests: 174
• Test/Code Ratio: 1.39:1
Test Coverage:
• Controller Methods Tested: 3/3 (100%)
• Endpoints Tested: 3/3 (100%)
• Security Decorators Tested: ✅
• Error Cases Tested: ✅
• Happy Path Cases: ✅
• Module Initialization: ⚠️ (Partial)
Classes & Handlers:
• Controllers: 1 (McpTransportController)
• Modules: 1 (McpIntegrationModule)
• Handlers: 0 (Not using CQRS)
• Entities: 0 (Not implemented)
• Services: 0 (Delegated to library)
================================================================================
6. TESTING PATTERNS & CONVENTIONS
================================================================================
Framework: Vitest
Config: apps/api/vitest.config.ts
• globals: true (vi, describe, it, expect available globally)
• environment: 'node'
• pattern: src/**/*.spec.ts
Common Patterns in Codebase:
Pattern A: Simple Handler Testing (Auth module)
├── Minimal mocking
├── Command objects for input
└── Focused assertions
Pattern B: Complex Handler Testing (Payments module)
├── Multiple dependency mocks
├── Business rule testing
├── Event bus verification
└── Error scenario coverage
Pattern C: Domain Entity Testing (Payments module)
├── Explicit vitest imports
├── Entity state transitions
├── Domain event verification
├── Value object testing
└── Helper factory functions
Pattern D: Infrastructure Service Testing (Zalopay service)
├── External service simulation
├── Crypto/security testing
├── Complex test data builders
└── Edge case coverage
================================================================================
7. RECOMMENDED TEST COMMANDS
================================================================================
Run all MCP tests:
$ pnpm test -- src/modules/mcp
Run specific test file:
$ pnpm test -- src/modules/mcp/presentation/__tests__/mcp-transport.controller.spec.ts
Run with watch mode:
$ pnpm test -- --watch src/modules/mcp
Run with coverage:
$ pnpm test -- --coverage src/modules/mcp
Run all tests (project-wide):
$ pnpm test
================================================================================
SUMMARY
================================================================================
The MCP module is a SIMPLIFIED integration layer that:
✅ Exposes 3 HTTP endpoints for MCP server access
✅ Handles SSE connection lifecycle
✅ Provides rate limiting and JWT authentication
✅ Well-tested at controller level (174 lines of tests)
Areas for Improvement:
⚠️ Module initialization not tested
⚠️ No domain layer implementation
⚠️ No application handlers (CQRS)
⚠️ No infrastructure adapters
The module follows project conventions:
✅ Vitest for testing
✅ vi.fn() for mocking
✅ Decorator verification with Reflect API
✅ Organized __tests__/ subdirectory
For additional test examples:
• Auth module: apps/api/src/modules/auth/application/__tests__/
• Payments module: apps/api/src/modules/payments/
• Search module: apps/api/src/modules/search/
================================================================================
Generated: April 11, 2026
================================================================================