Architecture
1. Overview
This module contains architecture documentation for the Event and Membership Administration System, including integration patterns, system design, and architectural decisions.
2. Document Categories
| Category | Description |
|---|---|
Integration Architecture |
Patterns for integrating with external systems and platforms |
System Design |
Core system architecture and component interactions |
Data Architecture |
Data models, flows, and persistence patterns |
3. Current Documentation
3.1. Service Patterns
-
Microservice Pattern — The shared deployment, build, CI/CD and observability baseline every EMS service follows. Read this first when bootstrapping anything new.
-
REST API Conventions — The contract every backend endpoint follows: bare-array collections +
X-Total-Count(ADR-0013), criteria filtering, enum wire format, status codes, errors. Read before adding or changing an endpoint. -
Portal Pattern — Gateway + Angular SPA topology, OIDC client, session-held JWT, server-side tenant resolution, same-origin browser scope.
-
MCP Pattern — OAuth resource server exposing admin-service via Model Context Protocol to LLM-driven clients (Cowork).
-
Java Library Pattern — Maven JAR artefacts published to GitHub Packages (parent-pom,
event-database,wordpress-database,spreadsheet-importer). Re-uses the CI/CD half of the microservice baseline; drops Jib / Helm / ArgoCD.
3.2. Portal Concerns
-
Gateway + Angular SPA — The canonical topology for EMS frontends: Spring Boot gateway + Angular SPA, session-held JWT, server-side tenant resolution, same-origin browser scope
-
OIDC ⇄ admin-service Token Exchange — Trust model, claim mapping, JIT provisioning, and the runtime-tenant-switch design gap
-
Session-Held JWT & JSESSIONID — Where the JWT lives, the relay filter, OIDC refresh state machine, logout, CSRF posture
-
API-Key Injection at the Gateway — Why portals authenticate themselves with X-API-KEY, gateway-side injection mechanics, rotation procedure
-
SPA Cache & CDN Strategy — Per-path-class cache-control rules, hashed assets immutable, index.html no-cache, Cloudflare CDN-Cache-Control
-
OpenAPI Contract Flow — admin-service as spec source of truth, CI extraction, in-portal TypeScript client generation, dayjs transformer
-
Hazelcast Configuration — Embedded member topology, four-tier discovery, session replication, EMS-custom security-dimension caches
-
SpringApplication Bootstrap — Shared main-class convention, profile validation, startup banner, profile inventory
-
Dev-Mode UI Awareness — webpack DefinePlugin flag, gated behaviours, proposed shared dev-banner component
-
JHipster — Keep & Drop — What we retain from JHipster conventions vs what we leave behind as we move to greenfield portals
3.3. Integration
-
Communication Integration - Multi-channel communication platform integration
-
Data Synchronisation - Bi-directional sync with external systems (TagServer, RunSignup)
3.4. File Import
-
File Import - XLSX and CSV spreadsheet import with dictionary-based column mapping
-
Async Import - Asynchronous import processing with interactive mapping resolution
-
Import Bookend Contract - Contract that lets a new import flow reuse the shared C05 host. Cookbook for adding bookends.
3.5. Async Processing
-
Signal & Sweep Framework — The unified asynchronous trigger framework: persistent signals, reactors, periodic sweeps, squash-on-emit debounce, database-backed leader election, and runtime enable/disable. Read this before adding any background processing (Feature #403)
3.6. Observability
-
Observability Platform — Why telemetry flows applications → OpenTelemetry → a self-hosted Grafana stack, what each component is configured to do, and how the platform is watched from outside its own failure domain.
3.7. Domain
-
RaceNumber Lifecycle - The state machine, audit trail, and self-healing guarantees (Feature #473)
4. Related Documentation
-
Requirements - Functional and non-functional requirements
-
Components - System component documentation
-
Security - Security architecture
5. Architecture Decision Records
Durable records of significant decisions — what was decided, why, and what alternatives were rejected. ADRs are read whenever someone asks "why did you do it this way?" or "why not the other way?".
-
ADR Index — full catalogue with status
-
ADR-0001: RaceNumber state transitions live in the service, not the callers
-
ADR-0002: Result import accepts IN_STOCK as implicit issuance
-
ADR-0003: Result import does not transition UNFIT_FOR_SERVICE
-
ADR-0006: Auto-assign latest-only; UNFIT-latest forces manual assignment
-
ADR-0007: Org-scoped member search returns person data directly
-
ADR-0009: Organisation scope is server-derived and schema-owned
-
ADR-0010: Public data is served by an unauthenticated API surface
-
ADR-0013: Collections return a bare array with pagination in headers
-
ADR-0014: Application meters are scraped; auto-instrumentation is pushed