Skip to the content.

Task 111 — Produces() + DTO рефакторинг (исключить анонимные типы)

Phase: 8 Status: pending Owner: — Slug: produces-dto-refactor Studio Stage: 0 (pre-req для качественного codegen)

Goal

Добавить .Produces<T>(statusCode) на каждый endpoint для типизированных response schemas в OpenAPI. Рефакторить все анонимные Results.Ok(new { ... }) в named DTOs. Создать чистый DTO слой. Полностью исключить анонимные типы из API responses.

Acceptance criteria

DTO placement strategy

src/agent/Hercules.WebApi/Contracts/
├── Chat/          — ChatRequest, ChatResponseDto (moved from Agent/WebApiAdapter.cs)
├── Skills/        — SkillDto, SkillDetailDto, CreateSkillRequest, UpdateSkillRequest, SkillEvaluationResultDto
├── Mesh/          — MeshAgentDto, MeshHealthDto, MeshDashboardDto, etc. (moved from Mesh/Dashboard/)
├── Config/        — ConfigDto
├── Memory/        — MemoryProfileDto, etc.
├── Stats/         — StatsDto, BudgetDto, etc.
├── Tools/         — ToolEntryDto, McpServerDto, etc.
├── Lifecycle/     — LifecycleInventoryDto, etc.
├── Audit/         — AuditEntryDto, AuditLogDto
├── Mesh/          — (moved from Mesh/Dashboard/MeshDashboardDtos.cs)
└── Common/        — HealthResponseDto, ErrorResponseDto, PaginatedResultDto<T>

Migration plan (по доменам)

Приоритет 1 — ключевые домены (Studio Stage 0-3)

Приоритет 2 — операционные домены (Studio Stage 4-6)

Приоритет 3 — остальные домены

Anonymous type → named DTO examples

// Before
app.MapGet("/api/health", () => Results.Ok(new { status = "ok", version = "1.0" }));

// After
app.MapGet("/api/health", () => Results.Ok(new HealthResponseDto("ok", "1.0")))
   .Produces<HealthResponseDto>(StatusCodes.Status200OK);

// Before
app.MapPost("/api/memory/reset", () => Results.Ok(new { status = "ok" }));

// After
app.MapPost("/api/memory/reset", () => Results.Ok(new StatusResponseDto("ok")))
   .Produces<StatusResponseDto>(StatusCodes.Status200OK);

Dependencies

Scope / Likely files

Risks / Rollback

Notes