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,56 @@
|
||||
---
|
||||
arc42: "4 — Solution Strategy"
|
||||
status: 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 |
|
||||
Reference in New Issue
Block a user