Skip to content

Technical Documentation

This section covers the engineering of Registry: the two-service architecture, the reactive backend, the Angular frontend, the data model and API contracts, the security model, and the Architecture Decision Records that justify each choice. It assumes the Functional Documentation — especially the Roles & Permissions baseline — is understood.

System at a glance

Registry is delivered as two independently versioned services plus two supporting infrastructure components:

The browser loads the SPA from nginx, which calls the backend over REST with a bearer JWT. Authentication is delegated to an external OIDC provider; the backend both validates JWTs (as a resource server) and brokers the code/refresh exchanges (as a confidential client). All state lives in a single PostgreSQL database.

Documentation map

PagePurpose
Getting StartedRun the whole stack locally: prerequisites, dependencies, and configuration
ArchitectureThe hexagonal backend, the Angular frontend, and how a request flows end to end
SecurityAuthentication flow, JWT-to-user mapping, and how the project-scoped RBAC is enforced
Data ModelThe PostgreSQL schema, entity relationships, auditing, and trigram search
API ReferenceEvery REST endpoint, grouped by domain, with its required permission
ADR indexAll Architecture Decision Records, in causal order

Stack summary

LayerBackendFrontend
LanguageKotlin 2.x (JVM toolchain 25)TypeScript 6
FrameworkSpring Boot 4.1 · WebFlux (reactive)Angular 22 (standalone)
ArchitectureHexagonal (ports & adapters), ArchUnit-enforcedDomain-driven folders, per-route lazy state
State / dataR2DBC (reactive) + Flyway migrationsNGXS (selectSignal), facade pattern
UIPrimeNG (Lara) + PrimeIcons
AuthOAuth2 resource server + confidential client (OIDC)OIDC redirect flow, token interceptor
API docsspringdoc OpenAPI (feature-flagged)
i18nmessages/errors bundles (en, fr)@ngx-translate (en, fr)
ObservabilityActuator + Micrometer/Prometheus
BuildGradle (Kotlin DSL)Angular CLI + pnpm
Runtime imageDistroless Java 25, non-root, JVM jarUnprivileged nginx serving the static bundle
PersistencePostgreSQL (pg_trgm trigram search)
Releasesemantic-release → GHCR (retain 5)semantic-release → GHCR (retain 5)

ADR format

Each ADR lives in adr/[NNN]-[short-title].md and follows this structure:

markdown
# ADR NNN — Title

## Status

Accepted | Superseded by ADR NNN | Deprecated

## Context

What problem or constraint triggered this decision?

## Decision

What was decided?

## Consequences

Positive and negative trade-offs, and why the alternatives were rejected.