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,135 @@
|
||||
---
|
||||
arc42: "5 — Building Block View"
|
||||
status: stub
|
||||
---
|
||||
|
||||
## 5.1 Level 1 — Maven Module Structure
|
||||
|
||||
```plantuml
|
||||
@startuml modules
|
||||
skinparam packageStyle rectangle
|
||||
|
||||
package "apix-common\n(plain Java 21 library)" as common {
|
||||
component [OLevel\nLivenessStatus\nBsmPayload\nServiceSummaryDto\nVerificationResult] as dtos
|
||||
}
|
||||
|
||||
package "apix-verification\n(plain Java 21 library)" as verification {
|
||||
component [O1DnsVerifier\nO2GleifVerifier\nO2OpenCorporatesVerifier\nO3HygieneVerifier\nSanctionsScreener\nVerificationPipeline] as verifiers
|
||||
}
|
||||
|
||||
package "apix-registry\n(Quarkus 3.x app)" as registry {
|
||||
component [IndexResource\nServiceResource\nRegisterResource] as res
|
||||
component [RegistryService\nVerificationOrchestrator] as svc
|
||||
component [ServiceRecord\nServiceRepository] as repo
|
||||
component [Liquibase\nmigrations] as lb
|
||||
}
|
||||
|
||||
package "apix-spider\n(Quarkus 3.x app)" as spider {
|
||||
component [SpiderScheduler\nLivenessFetcher\nLivenessEvaluator\nOpenApiParser\nMcpParser] as spider_core
|
||||
component [SpiderServiceView\nSpiderRepository] as spider_repo
|
||||
}
|
||||
|
||||
package "apix-portal\n(Quarkus 3.x app)" as portal {
|
||||
component [PortalResource\nAdminResource\nRegistryClient] as portal_res
|
||||
component [Qute templates] as templates
|
||||
}
|
||||
|
||||
verification ..> common : depends on
|
||||
registry ..> common : depends on
|
||||
registry ..> verification : depends on
|
||||
spider ..> common : depends on
|
||||
portal ..> common : depends on
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
## 5.2 Level 1 — Deployment View (Docker Compose)
|
||||
|
||||
```plantuml
|
||||
@startuml deploy_l1
|
||||
package "Docker Compose — Hetzner CX22" {
|
||||
component [Caddy\n:80 / :443] as caddy
|
||||
component [apix-registry\n:8180 (internal)] as registry
|
||||
component [apix-spider\n:8082 (internal only)] as spider
|
||||
component [apix-portal\n:8081 (internal)] as portal
|
||||
database [PostgreSQL 16\n:5432 (internal)] as db
|
||||
}
|
||||
|
||||
cloud Internet
|
||||
Internet --> caddy : HTTPS
|
||||
|
||||
caddy --> registry : /api/*
|
||||
caddy --> portal : /*
|
||||
registry --> db : Hibernate ORM (Liquibase owner)
|
||||
spider --> db : Hibernate ORM (Liquibase disabled)
|
||||
portal --> registry : REST Client (HTTP internal)
|
||||
spider --> [External Services] : liveness checks (HTTPS)
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
## 5.3 Level 2 — apix-registry Internals
|
||||
|
||||
```plantuml
|
||||
@startuml level2_registry
|
||||
package "apix-registry" {
|
||||
component [IndexResource] as r_index
|
||||
component [ServiceResource] as r_svc
|
||||
component [RegisterResource] as r_reg
|
||||
component [RegistryService] as svc
|
||||
component [VerificationOrchestrator] as orch
|
||||
component [ServiceRepository\n(Panache)] as repo
|
||||
component [Bean Validation\n(@Valid on JAX-RS)] as val
|
||||
}
|
||||
|
||||
r_index --> svc
|
||||
r_svc --> svc
|
||||
r_reg --> val
|
||||
r_reg --> svc
|
||||
r_reg --> orch
|
||||
svc --> repo
|
||||
orch --> [VerificationPipeline\n(apix-verification)]
|
||||
orch --> repo : persist VerificationResult
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
## 5.4 Level 2 — apix-spider Internals
|
||||
|
||||
```plantuml
|
||||
@startuml level2_spider
|
||||
package "apix-spider" {
|
||||
component [SpiderScheduler\n@Scheduled(every=15m)] as sched
|
||||
component [LivenessFetcher\n@RestClient\n@RunOnVirtualThread] as fetcher
|
||||
component [LivenessEvaluator\n(pure logic)] as eval
|
||||
component [OpenApiParser] as oa
|
||||
component [McpParser] as mcp
|
||||
component [SpiderRepository\n(Panache)] as repo
|
||||
}
|
||||
|
||||
sched --> repo : load services due for check
|
||||
sched --> fetcher : dispatch per service
|
||||
fetcher --> eval : HTTP status + response_ms
|
||||
fetcher --> oa : spec URL
|
||||
fetcher --> mcp : MCP URL
|
||||
eval --> repo : write LivenessStatus
|
||||
oa --> repo : write spec validation result
|
||||
mcp --> repo : write spec validation result
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
## 5.5 Component Responsibility Table
|
||||
|
||||
| Module / Component | Type | Responsibility |
|
||||
|---|---|---|
|
||||
| `apix-common` | Plain Java library | Shared enums and DTOs; no framework dependency; used by all modules |
|
||||
| `apix-verification` | Plain Java library | O-level elevation pipeline; pure logic + external HTTP/DNS calls via `java.net.http`; no Quarkus context |
|
||||
| `apix-registry` | Quarkus app | REST API (HATEOAS); BSM registration + validation; capability search; schema owner (Liquibase) |
|
||||
| `apix-spider` | Quarkus app | Scheduled liveness checks; OpenAPI/MCP spec verification; writes liveness metrics to DB; independent lifecycle |
|
||||
| `apix-portal` | Quarkus app | Human-readable web portal (HTMX + Qute); registration form; admin O-level view; calls registry via REST Client |
|
||||
| `VerificationOrchestrator` | CDI bean (registry) | Bridge between Quarkus config injection and the plain-Java `VerificationPipeline`; persists results |
|
||||
| `LivenessEvaluator` | Plain class (spider) | Pure function: HTTP status + response time → `LivenessStatus`; no I/O; testable without Quarkus |
|
||||
| `ServiceRecord` | Panache entity (registry) | Full entity — all columns; schema owner |
|
||||
| `SpiderServiceView` | Panache entity (spider) | Read/write subset of `services` table — only liveness columns; does not run migrations |
|
||||
| PostgreSQL | Database | Single shared instance; registry owns schema; spider and portal are consumers |
|
||||
Reference in New Issue
Block a user