Contract-first API with DTOs, validation, and server-side OpenAPI post-processing
Add dedicated request/response DTOs for all controllers, replacing raw JsonNode parameters with validated types. Move OpenAPI path-prefix stripping and ProcessorNode children injection into OpenApiCustomizer beans so the spec served at /api/v1/api-docs is already clean — eliminating the need for the ui/scripts/process-openapi.mjs post-processing script. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import com.cameleer3.server.core.agent.AgentInfo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "Agent instance summary")
|
||||
public record AgentInstanceResponse(
|
||||
@NotNull String id,
|
||||
@NotNull String name,
|
||||
@NotNull String group,
|
||||
@NotNull String status,
|
||||
@NotNull List<String> routeIds,
|
||||
@NotNull Instant registeredAt,
|
||||
@NotNull Instant lastHeartbeat
|
||||
) {
|
||||
public static AgentInstanceResponse from(AgentInfo info) {
|
||||
return new AgentInstanceResponse(
|
||||
info.id(), info.name(), info.group(),
|
||||
info.state().name(), info.routeIds(),
|
||||
info.registeredAt(), info.lastHeartbeat()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "Agent token refresh request")
|
||||
public record AgentRefreshRequest(@NotNull String refreshToken) {}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "Refreshed access token")
|
||||
public record AgentRefreshResponse(@NotNull String accessToken) {}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "Agent registration payload")
|
||||
public record AgentRegistrationRequest(
|
||||
@NotNull String agentId,
|
||||
@NotNull String name,
|
||||
@Schema(defaultValue = "default") String group,
|
||||
String version,
|
||||
List<String> routeIds,
|
||||
Map<String, Object> capabilities
|
||||
) {}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "Agent registration result with JWT tokens and SSE endpoint")
|
||||
public record AgentRegistrationResponse(
|
||||
@NotNull String agentId,
|
||||
@NotNull String sseEndpoint,
|
||||
long heartbeatIntervalMs,
|
||||
@NotNull String serverPublicKey,
|
||||
@NotNull String accessToken,
|
||||
@NotNull String refreshToken
|
||||
) {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "JWT token pair")
|
||||
public record AuthTokenResponse(
|
||||
@NotNull String accessToken,
|
||||
@NotNull String refreshToken
|
||||
) {}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "Result of broadcasting a command to multiple agents")
|
||||
public record CommandBroadcastResponse(
|
||||
@NotNull List<String> commandIds,
|
||||
int targetCount
|
||||
) {}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "Command to send to agent(s)")
|
||||
public record CommandRequest(
|
||||
@NotNull @Schema(description = "Command type: config-update, deep-trace, or replay")
|
||||
String type,
|
||||
@Schema(description = "Command payload JSON")
|
||||
Object payload
|
||||
) {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "Result of sending a command to a single agent")
|
||||
public record CommandSingleResponse(
|
||||
@NotNull String commandId,
|
||||
@NotNull String status
|
||||
) {}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "Error response")
|
||||
public record ErrorResponse(@NotNull String message) {}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "OIDC configuration update request")
|
||||
public record OidcAdminConfigRequest(
|
||||
boolean enabled,
|
||||
String issuerUri,
|
||||
String clientId,
|
||||
String clientSecret,
|
||||
String rolesClaim,
|
||||
List<String> defaultRoles,
|
||||
boolean autoSignup
|
||||
) {}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import com.cameleer3.server.core.security.OidcConfig;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "OIDC configuration for admin management")
|
||||
public record OidcAdminConfigResponse(
|
||||
boolean configured,
|
||||
boolean enabled,
|
||||
String issuerUri,
|
||||
String clientId,
|
||||
boolean clientSecretSet,
|
||||
String rolesClaim,
|
||||
List<String> defaultRoles,
|
||||
boolean autoSignup
|
||||
) {
|
||||
public static OidcAdminConfigResponse unconfigured() {
|
||||
return new OidcAdminConfigResponse(false, false, null, null, false, null, null, false);
|
||||
}
|
||||
|
||||
public static OidcAdminConfigResponse from(OidcConfig config) {
|
||||
return new OidcAdminConfigResponse(
|
||||
true, config.enabled(), config.issuerUri(), config.clientId(),
|
||||
!config.clientSecret().isBlank(), config.rolesClaim(),
|
||||
config.defaultRoles(), config.autoSignup()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "OIDC configuration for SPA login flow")
|
||||
public record OidcPublicConfigResponse(
|
||||
@NotNull String issuer,
|
||||
@NotNull String clientId,
|
||||
@NotNull String authorizationEndpoint,
|
||||
@Schema(description = "Present if the provider supports RP-initiated logout")
|
||||
String endSessionEndpoint
|
||||
) {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cameleer3.server.app.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "OIDC provider connectivity test result")
|
||||
public record OidcTestResult(
|
||||
@NotNull String status,
|
||||
@NotNull String authorizationEndpoint
|
||||
) {}
|
||||
Reference in New Issue
Block a user