Files
imfozilbek f46048172f feat: add entity exposure detection (v0.3.0)
Implement entity exposure detection to prevent domain entities
from leaking to API responses. Detects when controllers/routes
return domain entities instead of DTOs.

Features:
- EntityExposure value object with detailed suggestions
- IEntityExposureDetector interface in domain layer
- EntityExposureDetector implementation in infrastructure
- Integration into AnalyzeProject use case
- CLI display with helpful suggestions
- 24 comprehensive unit tests (98% coverage)
- Examples for bad and good patterns

Detection scope:
- Infrastructure layer only (controllers, routes, handlers, resolvers, gateways)
- Identifies PascalCase entities without Dto/Request/Response suffixes
- Parses async methods with Promise<T> return types
- Provides step-by-step remediation suggestions

Test coverage:
- EntityExposureDetector: 98.07%
- Overall project: 90.6% statements, 83.97% branches
- 218 tests passing

BREAKING CHANGE: Version bump to 0.3.0
2025-11-24 13:51:12 +05:00

59 lines
1.4 KiB
TypeScript

/**
* BAD EXAMPLE: Entity Exposure
*
* Guardian should detect:
* ❌ Domain entity returned from controller
* ❌ No DTO layer
*
* Why bad:
* - Exposes internal structure
* - Breaking changes propagate to API
* - Can't version API independently
* - Security risk (password fields, etc.)
* - Violates Clean Architecture
*/
class User {
constructor(
public id: string,
public email: string,
public passwordHash: string,
public isAdmin: boolean,
) {}
}
export class BadUserController {
/**
* ❌ BAD: Returning domain entity directly!
*/
public async getUser(id: string): Promise<User> {
return new User(id, "user@example.com", "hashed_password_exposed!", true)
}
/**
* ❌ BAD: Accepting domain entity as input!
*/
public async updateUser(user: User): Promise<User> {
return user
}
}
/**
* ✅ GOOD VERSION:
*
* // application/dtos/UserResponseDto.ts
* export interface UserResponseDto {
* readonly id: string
* readonly email: string
* // NO password, NO internal fields
* }
*
* // infrastructure/controllers/UserController.ts
* export class UserController {
* async getUser(id: string): Promise<UserResponseDto> {
* const user = await this.getUserUseCase.execute(id)
* return UserMapper.toDto(user) // Convert to DTO!
* }
* }
*/