Files
apix-mvp/docs/arc42/04-solution-strategy.md
Carsten Rehfeld b2a16a8be7 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>
2026-05-08 09:13:26 +02:00

57 lines
4.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 | ~5080MB 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 |