Implement apix-registry with IoT sunset/decommission lifecycle and full BDD suite
- REST API: register, patch, O-level, replacements, history, search endpoints - IoT lifecycle validations: future sunset, lock-before-release, sunset-passed-before-decommission - DB schema: Liquibase changesets 001–008 (services, versions, replacements, sunset-at column) - @ColumnTransformer(write="?::jsonb") on bsm_payload fields to avoid JDBC varchar→jsonb rejection - Jandex plugin on apix-common + quarkus.index-dependency so @NotBlank validators resolve at runtime - quarkus-logging-json extension added; quarkus.log.console.json=false is now a recognised key - Fix requireSunsetBeforeLockRelease: Boolean.TRUE.equals instead of !Boolean.FALSE.equals (null guard) - BDD suite: 27 scenarios / 213 steps across 5 feature files (sunset-lock, decommission, replacement, discovery, anonymity) - Test infrastructure: JDBC TRUNCATE in @Before for DB isolation, Arc.container() for clock control — no test endpoints in production code - sunsetAt truncated to microseconds in BDD steps to match Postgres timestamptz precision - Cucumber step fixes: singular/plural candidate(s), lastResponse propagation in replacementsReturnsNCandidates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.botstandards</groupId>
|
||||
<artifactId>apix-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>apix-common</artifactId>
|
||||
<name>APIX :: Common</name>
|
||||
<description>Shared enums, DTOs, and value types. No Quarkus dependency.</description>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.smallrye</groupId>
|
||||
<artifactId>jandex-maven-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-index</id>
|
||||
<goals>
|
||||
<goal>jandex</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Bean Validation API + @URL from Hibernate Validator annotations -->
|
||||
<dependency>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
<artifactId>jakarta.validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
<!-- Jackson annotations for JSON field naming / null-handling hints -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public record BsmPayload(
|
||||
@NotBlank String name,
|
||||
@NotBlank String description,
|
||||
@NotBlank @URL String endpoint,
|
||||
@NotEmpty List<@NotBlank String> capabilities,
|
||||
@NotBlank @Email String registrantEmail,
|
||||
@NotBlank String registrantName,
|
||||
@NotBlank String registrantJurisdiction,
|
||||
OrgType registrantOrgType,
|
||||
String registrantLei,
|
||||
@URL String openApiSpecUrl,
|
||||
@URL String mcpSpecUrl,
|
||||
@URL String policyUrl,
|
||||
@URL String securityContactUrl,
|
||||
@Valid Pricing pricing,
|
||||
@NotBlank String bsmVersion,
|
||||
ServiceStage serviceStage,
|
||||
// IoT transition fields — null for non-IoT services
|
||||
Boolean locked,
|
||||
Instant sunsetAt,
|
||||
@URL String migrationGuideUrl,
|
||||
List<UUID> replacesServiceIds
|
||||
) {
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public record Pricing(
|
||||
String billingModel,
|
||||
BigDecimal pricePerCall,
|
||||
String currency,
|
||||
String billingUnit
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
public enum ChangeType {
|
||||
REGISTERED,
|
||||
BSM_UPDATED,
|
||||
ORG_TYPE_CHANGED,
|
||||
OLEVEL_CHANGED,
|
||||
STAGE_CHANGED,
|
||||
OWNERSHIP_TRANSFERRED,
|
||||
REGISTRY_STATUS_CHANGED,
|
||||
SUNSET_DECLARED,
|
||||
LOCK_RELEASED,
|
||||
REPLACEMENT_DECLARED
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
public enum LivenessStatus {
|
||||
PENDING,
|
||||
LIVE,
|
||||
DEGRADED,
|
||||
UNREACHABLE
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
public enum OLevel {
|
||||
UNVERIFIED,
|
||||
IDENTITY_VERIFIED,
|
||||
LEGAL_ENTITY_VERIFIED,
|
||||
HYGIENE_VERIFIED,
|
||||
OPERATIONALLY_VERIFIED,
|
||||
AUDITED
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
public enum OrgType {
|
||||
INDIVIDUAL,
|
||||
COMMERCIAL,
|
||||
NON_PROFIT,
|
||||
GOVERNMENT,
|
||||
ACADEMIC
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
public enum RegistryStatus {
|
||||
ACTIVE,
|
||||
SUSPENDED,
|
||||
ARCHIVED
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
public enum ServiceStage {
|
||||
DEVELOPMENT,
|
||||
BETA,
|
||||
PRODUCTION,
|
||||
DEPRECATED,
|
||||
DECOMMISSIONED
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public record ServiceSummaryDto(
|
||||
UUID id,
|
||||
String name,
|
||||
List<String> capabilities,
|
||||
OLevel oLevel,
|
||||
LivenessStatus livenessStatus,
|
||||
ServiceStage serviceStage,
|
||||
RegistryStatus registryStatus,
|
||||
String endpoint,
|
||||
Instant lastCheckedAt
|
||||
) {}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.botstandards.apix.common;
|
||||
|
||||
public record VerificationResult(
|
||||
OLevel oLevelAchieved,
|
||||
String blockedAtStep,
|
||||
String message
|
||||
) {}
|
||||
Reference in New Issue
Block a user