b2a16a8be7
- 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>
4.0 KiB
4.0 KiB
arc42, status
| arc42 | status |
|---|---|
| 4 — Solution Strategy | stub |
4.1 Technology Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Language + framework | Java 21 + Quarkus 3.x | Compile-time safety; purpose-built for microservices; GraalVM native image first-class (see ADR-001) |
| Production binary | GraalVM Native Image | ~50–80MB RAM per service; ~100ms startup; fits Hetzner CX22 with headroom |
| Dev loop | quarkus dev (JVM mode) |
Live reload + continuous testing; native build only for production image |
| Persistence | Hibernate ORM + Panache | Standard Quarkus persistence; Panache active record reduces boilerplate |
| BSM payload | PostgreSQL JSONB + @JdbcTypeCode(SqlTypes.JSON) |
Flexible schema for optional BSM fields without a separate document store |
| Migrations | Liquibase | User's existing tool; first-class Quarkus extension; rollback + context support (see ADR-008) |
| Reverse proxy | Caddy | Auto-TLS with Let's Encrypt; minimal config (see ADR-003) |
| Portal rendering | HTMX + Qute | No JS build pipeline; type-safe templates (build-time error on missing variables); idiomatic Quarkus (see ADR-004) |
| Spider concurrency | Java 21 virtual threads (@RunOnVirtualThread) |
Non-blocking HTTP checks without reactive programming complexity |
| HTTP client (Spider) | Quarkus REST Client Reactive | Declarative; integrates with Quarkus DI and fault tolerance extensions |
| Build tool | Maven 3.9 | Quarkus documentation is Maven-first; Quarkus Maven plugin handles native build |
| Testing | JUnit 5 + @QuarkusTest + RestAssured + WireMock |
@QuarkusTest starts real application context; RestAssured for HTTP assertions; WireMock for external API mocks |
4.2 Architectural Patterns
| Pattern | Application |
|---|---|
| HATEOAS | IndexResource returns all navigation links; agents navigate from root without prior knowledge |
| Repository pattern | DB access in ServiceRepository (Panache); business logic in RegistryService; resources are thin |
| Compile-time DI | Quarkus CDI resolves all injection at build time; no runtime reflection surprises |
| Scheduler-based Spider | @Scheduled(every="15m") on SpiderScheduler; stateless per run; virtual threads for concurrent checks |
| Verification pipeline | Sequential O-level elevation (O-1 → sanctions → O-2 → O-3); each step is an independent CDI bean |
| API key on writes | Single shared key for MVP via custom Quarkus Security identity provider; per-registrant keys post-MVP |
| Fail-fast validation | BSM validated at boundary via Bean Validation (@Valid on JAX-RS resource); invalid BSM rejected with 400 + constraint violation details |
4.3 Quality Goal → Decision Mapping
| Quality Goal | Architecture Decision |
|---|---|
| Compile-time safety | Quarkus CDI + Bean Validation + Qute type-safe templates — errors at build time, not runtime |
| Queryability | HATEOAS root + capability search; JPQL + JSONB operator query in ServiceRepository |
| Liveness accuracy | SpiderScheduler every 15 min; last_checked_at + uptime_30d_percent exposed in response |
| Registration reliability | Idempotent UPSERT on endpoint URL; Liquibase migrations with rollback support |
| Security hygiene | HTTPS via Caddy; API key on write endpoints; no PII in logs; non-root container user |
| Solo maintainability | Docker Compose; quarkus dev for local loop; single JVM language across all services |
4.4 MVP Shortcuts (Accepted Technical Debt)
| Shortcut | Exit Path |
|---|---|
| O-4 / O-5 assigned manually | Accredited Verifier integration post-MVP |
| Single shared API key | Per-registrant key management + OAuth2 post-MVP |
| No rate limiting on read endpoints | Caddy rate_limit directive when traffic warrants |
| OpenAPI / MCP parsers validate presence only | Field-level spec comparison in Spider post-MVP |
| Single-region deployment | Hetzner multi-region + Managed Database post-funding |
| No billing | Commercial tier in Phase 2 |
| No CI/CD pipeline | GitHub Actions native build pipeline post-MVP |