Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions aep-core/src/main/java/foundation/aep/core/AepJson.java
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ public static PlatformAgentIdentityListResponse parsePlatformAgentIdentityListRe
Map<String, Object> value = object(json, PLATFORM_AGENT_IDENTITY_LIST);
AepRawJson.requireMembers(value, PLATFORM_AGENT_IDENTITY_LIST, "count", "data", "total");
AepRawJson.rejectNullPaths(value, PLATFORM_AGENT_IDENTITY_LIST, "count", "data", "total");
AepRawJson.requireStrings(value, PLATFORM_AGENT_IDENTITY_LIST, "count", "total");
return parse(
json,
PlatformAgentIdentityListResponse.class,
Expand Down
5 changes: 3 additions & 2 deletions aep-core/src/main/java/foundation/aep/core/AepRawJson.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static void claimValues(Map<String, Object> value) {
"person.username");
requireStrings(
value,
CLAIM_VALUES,
"contact.email",
"contact.mobile",
"person.birthdate",
Expand Down Expand Up @@ -140,11 +141,11 @@ static void requireMembers(Map<String, Object> value, String documentType, Strin
}
}

private static void requireStrings(Map<String, Object> value, String... members) {
static void requireStrings(Map<String, Object> value, String documentType, String... members) {
for (String member : members) {
if (value.containsKey(member) && !(value.get(member) instanceof String)) {
throw new AepValidationException(
CLAIM_VALUES, List.of(new ValidationIssue("$." + member, "Expected a string.")));
documentType, List.of(new ValidationIssue("$." + member, "Expected a string.")));
}
}
}
Expand Down
26 changes: 20 additions & 6 deletions aep-core/src/main/java/foundation/aep/core/AepValidation.java
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,8 @@ public static PlatformAgentIdentity requirePlatformAgentIdentity(PlatformAgentId
public static List<ValidationIssue> platformAgentIdentityListResponse(PlatformAgentIdentityListResponse value) {
Issues issues = new Issues();
if (value == null) return issues.required("$", JSON_OBJECT).values();
nonNegativeIntegerString(value.count(), "$.count", issues);
nonNegativeIntegerString(value.total(), "$.total", issues);
java.math.BigInteger count = nonNegativeIntegerString(value.count(), "$.count", issues);
java.math.BigInteger total = nonNegativeIntegerString(value.total(), "$.total", issues);
if (value.data() == null) {
issues.required("$.data", "array");
} else {
Expand All @@ -369,10 +369,14 @@ public static List<ValidationIssue> platformAgentIdentityListResponse(PlatformAg
"$.data[" + index + "]",
platformAgentIdentity(value.data().get(index)));
}
if (nonNegativeInteger(value.count()) != value.data().size()) {
if (count != null
&& !count.equals(java.math.BigInteger.valueOf(value.data().size()))) {
issues.add("$.count", "Expected count to equal the number of data entries.");
}
}
if (count != null && total != null && total.compareTo(count) < 0) {
issues.add("$.total", "Expected total not to be less than count.");
}
return issues.values();
}

Expand Down Expand Up @@ -794,11 +798,21 @@ private static void positiveIntegerString(String value, String path, Issues issu
}
}

private static void nonNegativeIntegerString(String value, String path, Issues issues) {
int number = nonNegativeInteger(value);
if (number < 0 || !Integer.toString(number).equals(value)) {
private static java.math.BigInteger nonNegativeIntegerString(String value, String path, Issues issues) {
if (value == null) {
issues.add(path, "Expected a non-negative decimal integer string.");
return null;
}
java.math.BigInteger number;
try {
number = new java.math.BigInteger(value);
} catch (NumberFormatException exception) {
issues.add(path, "Expected a non-negative decimal integer string.");
return null;
}
if (number.signum() >= 0 && number.toString().equals(value)) return number;
issues.add(path, "Expected a non-negative decimal integer string.");
return null;
}

private static int nonNegativeInteger(String value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,36 @@ void rejectsMalformedPlatformDiscoveryTemplatesWithoutThrowing() {
assertEquals(2, AepValidation.platformDiscoveryDocument(malformed).size());
}

@Test
void validatesPlatformIdentityListPagination() {
PlatformAgentIdentity identity = new PlatformAgentIdentity(
"did:web:p.example:a:4Yf7p2xQd9",
"pai_01J0AEPPLATFORM000000000001",
"2026-07-06T12:00:00Z",
"https://p.example/a/4Yf7p2xQd9/did.json",
"did:web:p.example:a:4Yf7p2xQd9",
"did:web:api.service.example",
List.of("ES256"),
ManagedAgentStatus.ACTIVE,
"2026-07-06T12:00:00Z");

assertTrue(AepValidation.platformAgentIdentityListResponse(
new PlatformAgentIdentityListResponse("1", List.of(identity), "999999999999999999999999"))
.isEmpty());
assertEquals(
"$.count",
AepValidation.platformAgentIdentityListResponse(
new PlatformAgentIdentityListResponse("0", List.of(identity), "1"))
.get(0)
.path());
assertEquals(
"$.total",
AepValidation.platformAgentIdentityListResponse(
new PlatformAgentIdentityListResponse("1", List.of(identity), "0"))
.get(0)
.path());
}

private static PlatformDiscoveryDocument discovery() {
return new PlatformDiscoveryDocument(
"1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ void parsesWireAuthorizationValues() {
AepJson.write(foundation.aep.core.ProblemDetails.of("invalid_request", "Invalid request", 400)));
}

@Test
void rejectsNumericPlatformPaginationFields() {
assertThrows(
AepValidationException.class,
() -> AepJson.parsePlatformAgentIdentityListResponse("{\"count\":0,\"data\":[],\"total\":\"0\"}"));
assertThrows(
AepValidationException.class,
() -> AepJson.parsePlatformAgentIdentityListResponse("{\"count\":\"0\",\"data\":[],\"total\":0}"));
}

@Test
void parsesEveryCoreWireDocument() {
assertEquals(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ void parsesWireAuthorizationValues() {
AepJson.write(foundation.aep.core.ProblemDetails.of("invalid_request", "Invalid request", 400)));
}

@Test
void rejectsNumericPlatformPaginationFields() {
assertThrows(
AepValidationException.class,
() -> AepJson.parsePlatformAgentIdentityListResponse("{\"count\":0,\"data\":[],\"total\":\"0\"}"));
assertThrows(
AepValidationException.class,
() -> AepJson.parsePlatformAgentIdentityListResponse("{\"count\":\"0\",\"data\":[],\"total\":0}"));
}

@Test
void parsesEveryCoreWireDocument() {
assertEquals(
Expand Down