Acknowledgements

This architecture documentation is based on arc42 - a great, freely available template for documenting software and system architectures.

Created, maintained and © by Dr. Peter Hruschka, Dr. Gernot Starke and contributors.

arc42 Logo


1. Introduction and Goals

Einsatzbereit is an open-source platform that connects engaged volunteers with regional needs. Volunteering and concrete societal benefit are always at the forefront.

The platform follows three guiding principles:

  • Volunteering first: Every decision - whether a feature, an architectural choice, or a process - serves the goal of making voluntary engagement easier.

  • Simple code: The source code should be simple enough that anyone can contribute, even without deep prior knowledge.

  • No baggage: Maintaining the platform should not be a burden; it should remain a lightweight helper.

1.1. Requirements Overview

Volunteering doesn’t require a long-term commitment. Sometimes an afternoon is enough, sometimes a week. But finding out where help is currently needed is often difficult - whether at large NGOs or a local sports tournament. Existing platforms are too complex, too generic, or barely used.

Einsatzbereit solves this by making concrete needs visible: what is needed, where, and when.

Key functional requirements:

  • Organizations and clubs can post volunteer opportunities with location, timeframe, and required skills.

  • Volunteers can search for matching opportunities in their region and sign up.

  • Usage is possible without any long-term commitment.

Table 1. Business Goals
Goal Description

Strengthen volunteering

Make voluntary engagement visible and accessible - without bureaucratic hurdles or long-term obligations.

Open and sustainable

The project is licensed under GNU AGPL v3.0. No profit, no closed source, no lost knowledge. It is secondary who develops the project further - the benefit to society comes first.

Low entry barrier

The entry barrier should be as low as possible for both users and contributors.

1.2. Quality Goals

The following quality goals define the essential quality requirements for Einsatzbereit and serve as a guide for architectural decisions.

Table 2. Primary Quality Goals
Quality Attribute Description Weight

Appropriateness

Every feature directly serves volunteering. No feature-bloat, no over-engineering - only what concretely increases value for volunteers or organizations.

Very High

Simplicity

Code and architecture are designed so that new contributors can understand them without deep prior knowledge. New features can be implemented without understanding the whole system. Simplicity takes precedence over flexibility.

High

Maintainability

The platform can be operated and evolved with minimal effort. Dependencies and build processes work with standard tooling. Maintenance should be a matter of course, not a burden.

High

Usability

The platform is intuitively usable. Volunteers and organizations can complete their tasks without onboarding or technical knowledge.

High

A complete list of all quality goals with detailed scenarios can be found in Chapter 10 Quality Requirements.

1.3. Stakeholders

Role Contact Expectations

Volunteers

End users

"I have a free Saturday afternoon and want to do something meaningful - but please without fighting through three forms first."

Volunteer Vera expects an intuitive interface where she can quickly find suitable opportunities without registration hurdles or obligations.

Organizations and clubs

End users

"We need ten people for setup this weekend. I want to post that in five minutes, not fifty."

Organizer Olaf expects a simple way to post volunteer opportunities and reach volunteers without any technical knowledge.

Contributors

GitHub Issues and Pull Requests

"I want to contribute a feature over a weekend, not spend two days just understanding the project."

Contributor Caro expects simple, well-structured code, clear contribution guidelines, and documentation that makes getting started easy.

Maintainers

GitHub Repository

"The less I have to fix at 2am, the better. Keep it simple, automate it, done."

Maintainer Milo expects low maintenance overhead through simple architecture, automated CI/CD pipelines, and few external dependencies.

2. Architecture Constraints

2.1. Technical Constraints

Table 3. Technical Constraints
Constraint Rationale

Docker and Docker Compose required for local development

All services (frontend, backend, Keycloak, PostgreSQL, pgAdmin) run in containers. This ensures a consistent development environment across all contributor machines.

GNU AGPL v3.0 license

All dependencies must be compatible with AGPL v3.0. Commercial or proprietary dependencies are excluded. Any deployment of the platform - including modifications - must be released under the same license.

Self-hosted only - no US cloud dependencies

Keycloak, PostgreSQL, and all supporting infrastructure run self-hosted. No dependency on US-based cloud providers (AWS, Azure, Google Cloud) to ensure data sovereignty and GDPR compliance.

PlantUML for architecture diagrams

All architecture diagrams are written as PlantUML source files and rendered via asciidoctor-diagram. No binary diagram files are committed to the repository.

NSwag-generated API client - never hand-edited

The frontend API client (api-client.ts) is generated from the OpenAPI spec. Manual edits to this file are prohibited; changes must go through the backend OpenAPI definition.

AsciiDoc for documentation

Architecture documentation follows the arc42 template written in AsciiDoc. Markdown is not used for structured documentation.

2.2. Organizational Constraints

Table 4. Organizational Constraints
Constraint Rationale

Open-source, volunteer-driven project

All contributors are volunteers. Processes and tooling must respect that contributors have limited time. Complexity that requires hours of setup is unacceptable.

Single maintainer (currently)

The project is currently maintained by one person. Architectural decisions must minimize the operational and maintenance burden. Automation is preferred over manual processes.

Minimal external service dependencies

Every external service dependency is an operational responsibility. Dependencies are added only when they provide significant value that cannot be achieved with reasonable effort otherwise.

Conventional Commits for all commits

All commits follow the Conventional Commits specification (feat:, fix:, docs:, etc.) to enable automated changelog generation and clear history.

2.3. Conventions

Table 5. Conventions
Convention Description

Feature folder structure

Both backend and frontend organize code by feature: {Layer}/{Domain}/{Feature}/v1/. This keeps related code co-located and makes finding things predictable.

API versioning via URL path

All API routes include the version in the path (/v1/…​). Breaking changes require a new version namespace.

Async all the way

No .Result or .Wait() calls in the backend. All I/O operations use async/await throughout the call stack.

English UI and code, multilingual support

The user interface, end-user documentation, and all code, commits, issues, and pull requests are in English. The UI supports multiple languages via internationalization.

3. Context and Scope

3.1. Business Context

business context
Figure 1. Business Context View
Table 6. Element Descriptions
Element Description

Volunteer Vera

Searches for opportunities to volunteer regionally. Wants to find concrete needs quickly without long-term commitment.

Organizer Olaf

Creates and manages volunteer opportunities for their organization or club. Posts what help is needed, where, and when.

Einsatzbereit

Connects volunteers with organizations by managing regional volunteer opportunities and registrations.

3.2. Technical Context

technical context
Figure 2. Technical Context View
Table 7. External Interfaces
Interface Direction Description

Browser → Frontend

Inbound

Users access the platform via a modern web browser. The frontend is a React SPA served as static assets.

Frontend → Backend API

Outbound

The SPA communicates with the backend via a versioned REST API over HTTPS. All requests carry a JWT Bearer token for authentication.

Frontend → Keycloak

Outbound

Authentication is handled via OIDC Authorization Code Flow with PKCE. The frontend redirects to Keycloak for login and receives tokens upon success.

Backend → Keycloak

Outbound

The backend validates incoming JWT tokens by checking signatures against Keycloak’s public JWKS endpoint.

Backend → PostgreSQL

Outbound

The backend persists all application data (volunteer opportunities, organizations, engagements) in PostgreSQL via EF Core.

GitHub Actions → GHCR

Outbound

CI/CD pipelines build Docker images on push to main and publish them to GitHub Container Registry.

Table 8. Mapping: Business Interface → Technical Interface
Business Interaction Technical Realization

Volunteer searches for opportunities

GET /v1/volunteer-opportunities with optional filter parameters, authenticated via JWT

Volunteer signs up for an opportunity

POST /v1/engagements with opportunity ID, authenticated via JWT

Organizer creates a volunteer opportunity

POST /v1/volunteer-opportunities with opportunity data, requires organisator role in JWT

Organizer manages their opportunities

GET, PUT, DELETE /v1/volunteer-opportunities/{id}, requires organisator role

4. Solution Strategy

The following table summarizes the key architectural decisions and how they address the project’s quality goals.

Table 9. Solution Strategy Overview
Quality Goal Architectural Decision Rationale

Simplicity

Clean Architecture with flat layer hierarchy (Domain → Application → Infrastructure → API)

Clear separation of concerns without deep nesting. Each layer has a single, well-defined responsibility. New contributors can navigate the codebase without understanding the whole system.

Simplicity

CQRS via MediatR (commands and queries as C# records)

Each use case is encapsulated in one handler class. Finding the code for a feature means finding one file. No large service classes accumulating unrelated logic.

Appropriateness

Feature folder structure in both backend and frontend

Code is organized by domain feature, not by technical layer. Adding a new feature means adding a new folder - not modifying multiple existing ones.

Maintainability

NSwag-generated API client for the frontend

The frontend API client is always in sync with the backend OpenAPI spec. Manual drift between API definition and client is impossible.

Maintainability

Monorepo with centralized dependency management (Directory.Packages.props)

All NuGet package versions are managed in a single file. Version updates require one change, not many.

Maintainability

.NET Aspire AppHost for local development

One command (dotnet run --project backend/src/Aspire/AppHost) starts the entire stack - Postgres, Keycloak, backend API, and the Vite frontend. No manual setup of databases, Keycloak realms, or service dependencies.

Maintainability

GitHub Actions CI/CD → GHCR

Automated builds, tests, and image publishing on every push to main. No manual release steps.

Usability

Keycloak for authentication and authorization

Volunteers and organizers get a polished login experience without the platform needing to implement authentication itself. Role-based access control (user, organisator, admin) is managed centrally.

Usability

React 19 SPA with Tailwind CSS 4

Modern, responsive single-page application. Fast navigation without full page reloads. Tailwind enables consistent styling without large CSS frameworks.

Openness

GNU AGPL v3.0 license

Ensures all derivative works remain open source. Prevents the platform from being forked into a closed-source product.

4.1. Technology Decisions at a Glance

Component Technology

Backend framework

.NET 10, ASP.NET Core Minimal API

ORM

EF Core 9 with PostgreSQL provider

CQRS / Mediator

MediatR

Authentication / Authorization

Keycloak 26.6.4, OIDC, JWT Bearer

Database

PostgreSQL 18

Frontend framework

React 19, Vite, TypeScript

Styling

Tailwind CSS 4

API client generation

NSwag (OpenAPI → TypeScript)

Local orchestration

.NET Aspire AppHost (Docker for service containers)

CI/CD

GitHub Actions → GitHub Container Registry (GHCR)

Architecture documentation

arc42, AsciiDoc, PlantUML

5. Building Block View

5.1. Level 1: System Overview (Whitebox)

container view
Figure 3. Container View - Einsatzbereit
Motivation

The system consists of four main containers: a React SPA for the UI, an ASP.NET Core API for business logic, Keycloak for identity management, and PostgreSQL for persistence. Authentication is centralized in Keycloak - neither the frontend nor the backend implements login logic directly.

Contained Building Blocks
Container Technology Responsibility

Single Page Application

React 19, Vite, TypeScript, Tailwind CSS 4

Provides the web UI for volunteers and organizers. Handles OIDC login redirect and token storage. Communicates with the backend API using a NSwag-generated client.

Backend API

.NET 10, ASP.NET Core, Clean Architecture

Exposes the versioned REST API. Implements all business logic via CQRS handlers. Validates JWT tokens, enforces role-based authorization, persists data via EF Core.

Identity Provider

Keycloak 26.6.4

Handles user authentication via OIDC Authorization Code Flow. Manages users, roles (user, organisator, admin), and organizations. Issues and signs JWT access tokens.

Application Database

PostgreSQL 18

Stores all application data: volunteer opportunities, organizations, engagements, and user associations.

Important Interfaces
Interface Description

Frontend ↔ Backend API

REST over HTTPS, versioned (/v1/…​). All requests carry a JWT Bearer token. Response format is JSON. The TypeScript client is generated from the OpenAPI spec.

Frontend ↔ Keycloak

OIDC Authorization Code Flow with PKCE. Frontend redirects to Keycloak for login; receives access and refresh tokens on success.

Backend ↔ Keycloak

Backend fetches Keycloak’s JWKS endpoint to validate JWT signatures. No direct Keycloak admin API calls in the application path.

Backend ↔ PostgreSQL

EF Core 9 over TCP. Migrations are applied on startup.

5.2. Level 2: Backend API (Whitebox)

component backend
Figure 4. Backend Component View - Clean Architecture

The backend follows Clean Architecture with four layers. Dependencies flow inward only: API → Application → Domain. Infrastructure implements interfaces defined in Application.

5.2.1. API Layer

Responsibility

Routes HTTP requests to the Application layer. Applies authentication middleware. Handles versioning and request/response serialization.

Interfaces

Exposes versioned ASP.NET Core Minimal API endpoints. Registers MediatR and reads JWT Bearer tokens via ASP.NET Core middleware.

Location

backend/src/Api/

5.2.2. Application Layer

Responsibility

Implements all use cases as CQRS command and query handlers. Defines repository interfaces used for data access.

Interfaces

MediatR IRequest/IRequestHandler contracts. Repository interfaces (IVolunteerOpportunityReadRepository, etc.).

Location

backend/src/Application/

5.2.3. Domain Layer

Responsibility

Contains core business entities as plain C# classes/records. No framework dependencies. Defines business rules as domain logic.

Location

backend/src/Domain/

5.2.4. Infrastructure Layer

Responsibility

Implements repository interfaces using EF Core. Manages database schema via migrations. Wires up all services in ServiceCollectionExtensions.

Location

backend/src/Infrastructure/

5.3. Level 2: Frontend SPA (Whitebox)

5.3.1. Pages

Responsibility

Top-level route components. Each page corresponds to a route and composes components.

Location

frontend/src/pages/

5.3.2. Components

Responsibility

Reusable UI building blocks. Stateless or locally stateful React components styled with Tailwind CSS.

Location

frontend/src/components/

5.3.3. API Client

Responsibility

NSwag-generated TypeScript client. Provides typed methods for all backend endpoints. Never hand-edited.

Location

frontend/src/client/api-client.ts

6. Runtime View

6.1. User Login (OIDC Authorization Code Flow)

A volunteer or organizer opens the application and authenticates via Keycloak using the OIDC Authorization Code Flow with PKCE.

runtime login
Figure 5. Runtime: User Login

Key aspects of this flow:

  • The frontend never handles passwords - authentication is fully delegated to Keycloak.

  • PKCE prevents authorization code interception attacks in the public client (SPA).

  • Tokens are stored in memory (not localStorage) to reduce XSS risk.

  • The access token is a short-lived JWT; the refresh token is used to obtain new access tokens silently.

6.2. Browse Volunteer Opportunities

A volunteer opens the opportunities page. The frontend fetches the list from the backend API, which validates the JWT and queries PostgreSQL.

runtime browse
Figure 6. Runtime: Browse Volunteer Opportunities

Key aspects:

  • Every API request carries the JWT Bearer token in the Authorization header.

  • The backend validates the token signature using Keycloak’s public JWKS keys (cached locally).

  • No session state is held server-side - the backend is stateless.

6.3. Create Volunteer Opportunity

An organizer fills out the opportunity form and submits it. The backend validates the JWT, checks the organisator role, and persists the new opportunity.

runtime create
Figure 7. Runtime: Create Volunteer Opportunity

Key aspects:

  • Role authorization (organisator) is enforced at the endpoint level via ASP.NET Core authorization policies.

  • The MediatR command handler performs input validation before writing to the database.

  • The response includes the created opportunity’s ID so the frontend can redirect to the detail page.

7. Deployment View

7.1. Infrastructure Level 1: Local Development (.NET Aspire)

deployment local
Figure 8. Deployment View - Local Development
Motivation

The entire stack runs locally via the .NET Aspire AppHost: a single dotnet run --project backend/src/Aspire/AppHost command provisions Postgres, Keycloak, the backend API, and the Vite frontend. This ensures environment parity across all contributor machines and eliminates manual setup of databases, Keycloak, or service dependencies.

Quality and Performance Characteristics

Local development is optimized for fast iteration, not production performance. All services run on localhost with no TLS. Keycloak realm configuration is imported automatically on first start from a versioned JSON file.

Table 10. Service Allocation
Service Image Port Notes

Frontend

ghcr.io/maik-hasler/einsatzbereit/frontend

4321

Vite dev server with hot module replacement

Backend API

ghcr.io/maik-hasler/einsatzbereit/backend

5000

ASP.NET Core, runs EF Core migrations on startup

Keycloak

ghcr.io/maik-hasler/einsatzbereit/keycloak

8080

Custom image with pre-imported einsatzbereit realm

PostgreSQL

postgres:18

5432

Two databases: einsatzbereit (app data) and keycloak (realm data)

pgAdmin

dpage/pgadmin4

5050

Pre-configured server connection to PostgreSQL

7.2. Infrastructure Level 2: CI/CD Pipeline

deployment cicd
Figure 9. Deployment View - CI/CD (GitHub Actions)

The CI/CD pipeline runs on GitHub Actions and covers two concerns: quality gates and image publishing.

7.2.1. Quality Gate (on every push / PR)

  • Backend: dotnet build + dotnet test (integration tests via Testcontainers)

  • E2E: dotnet test backend/tests/VisualTests (TUnit.Playwright against the full Aspire-provisioned stack)

  • Architecture docs: Asciidoctor build → GitHub Pages deployment

7.2.2. Image Publishing (on tag push)

Images are published to GitHub Container Registry (GHCR) on version tag pushes. A single Git tag triggers the release of all components with the same version:

Component Tag format Example

Frontend

v{semver}

v1.0.0

Backend

v{semver}

v1.0.0

Keycloak

v{semver}

v1.0.0

See [VERSIONING.md](../../VERSIONING.md) for the full versioning and publishing strategy.

8. Cross-cutting Concepts

8.1. Authentication and Authorization

Authentication and authorization are fully delegated to Keycloak. The application itself does not implement login, password management, or session handling.

Authentication flow (OIDC Authorization Code Flow with PKCE):

  1. The frontend redirects the browser to Keycloak’s authorization endpoint with a code_challenge.

  2. The user authenticates at Keycloak (username/password or SSO).

  3. Keycloak redirects back to the frontend with an authorization code.

  4. The frontend exchanges the code + code_verifier for an access token and refresh token.

  5. All subsequent API requests include the access token as a JWT Bearer token.

Authorization:

Role-based access control is enforced at the API endpoint level using ASP.NET Core authorization policies. Roles are embedded in the JWT as claims and originate from Keycloak.

Role Permissions

user

Browse volunteer opportunities, register for opportunities

organisator

All user permissions + create, update, and delete own organization’s opportunities

admin

Full administrative access

Token handling in the frontend:

Access tokens are stored in memory (React state / context), not in localStorage or sessionStorage, to reduce XSS attack surface. The refresh token is used to obtain new access tokens silently when the access token expires.

8.2. CQRS (Command Query Responsibility Segregation)

All use cases in the application layer follow the CQRS pattern via MediatR.

  • Queries are read-only operations. They return data and do not modify state. Queries use dedicated read repository interfaces (IVolunteerOpportunityReadRepository) and may use optimized read paths (e.g., projections) without loading full aggregate state.

  • Commands are state-changing operations. They return only what is needed (e.g., the created entity’s ID) and enforce business rules before writing.

Each use case lives in its own folder under {Layer}/{Domain}/{Feature}/v1/ and consists of the request record, the handler, and the response record. This makes every use case self-contained and easy to locate.

8.3. Error Handling

Error handling follows a consistent pattern across the stack:

Backend:

  • Domain validation errors are returned as 400 Bad Request with a structured error body.

  • Authorization failures result in 401 Unauthorized or 403 Forbidden.

  • Not-found cases return 404 Not Found.

  • Unhandled exceptions are caught by global exception middleware and returned as 500 Internal Server Error with a correlation ID for log tracing - no stack traces leak to clients.

Frontend:

  • API errors are surfaced to the user via inline error messages, not generic alerts.

  • Network errors (offline, timeout) are handled gracefully with retry options where appropriate.

  • The NSwag-generated client throws typed exceptions matching the backend’s HTTP status codes.

8.4. Database Migrations

Database schema changes are managed via EF Core migrations.

  • Migrations are stored under backend/src/Infrastructure/Persistence/Migrations/.

  • On application startup, pending migrations are applied automatically (database.MigrateAsync()).

  • Migration files are committed to the repository alongside the code changes that require them.

  • There is no separate migration deployment step - the application handles its own schema.

8.5. API Versioning

All API routes include the version in the URL path: /v{version}/…​.

  • The current version is v1.

  • Breaking changes (removed fields, changed semantics, renamed endpoints) require a new version.

  • Non-breaking additions (new optional fields, new endpoints) can be added to the existing version.

  • The NSwag-generated client is regenerated after any API change to keep the frontend in sync.

8.6. Logging and Observability

The backend uses the .NET built-in ILogger<T> abstraction. Structured logging is configured to output JSON in production environments and human-readable format during local development.

Key logged events:

  • All unhandled exceptions (with correlation ID)

  • Authentication failures

  • Database migration execution

  • Startup configuration summary

No external observability service (Datadog, Grafana, etc.) is currently integrated - this is a deliberate trade-off to keep operational complexity minimal.

9. Architecture Decisions

The following table lists the relevant architecture decisions. Each decision links to the corresponding ADR with full context, rationale, and considered alternatives.

Table 11. Architecture Decisions
No. Context Description Status Date ADR

1

Monorepo

Manage all components in a single repository.

Accepted

2026-03-23

Monorepo

2

arc42

Use arc42 as the template for architecture documentation.

Accepted

2026-03-25

arc42

3

Keycloak

Use Keycloak as the Identity and Access Management solution.

Accepted

2026-03-25

Keycloak

10. Quality Requirements

10.1. Quality Goals Overview

The following table lists all quality goals for the system, sorted by weight. These goals and their scenarios serve as a guide for architectural decisions.

Table 12. Complete List of Quality Goals
Quality Attribute Description Weight

Appropriateness

Every feature directly serves volunteering. No feature-bloat, no over-engineering - only what concretely increases value for volunteers or organizations.

Very High

Simplicity

Code and architecture are designed so that new contributors can understand them without deep prior knowledge. New features can be implemented without understanding the whole system. Simplicity takes precedence over flexibility.

High

Maintainability

The platform can be operated and evolved with minimal effort. Dependencies and build processes work with standard tooling. Maintenance should be a matter of course, not a burden.

High

Usability

The platform is intuitively usable. Volunteers and organizations can complete their tasks without onboarding or technical knowledge.

High

10.2. Quality Tree

quality tree
Figure 10. Quality Tree

10.3. Quality Scenarios

10.3.1. Appropriateness

ID Scenario Notes

QS-1.1

A new feature is proposed.

Before implementation, it is evaluated whether the feature concretely increases value for volunteers or organizations. Features without a clear connection to volunteering are rejected.

QS-1.2

The architecture is to be extended with a new abstraction layer.

The extension is only implemented if it addresses a concrete, current need - not for hypothetical future requirements.

10.3.2. Simplicity

ID Scenario Notes

QS-2.1

A new contributor wants to make their first code contribution.

The person can understand the code without deep prior knowledge and make a first contribution within a day. The CONTRIBUTING.md and project structure are self-explanatory.

QS-2.2

A new feature is to be implemented.

The change can be made without understanding the entire system. The affected component is clearly bounded.

QS-2.3

A contributor reads the source code of a component for the first time.

Through flat hierarchies, few abstraction levels, and clear naming, the code is understandable without additional documentation.

10.3.3. Maintainability

ID Scenario Notes

QS-3.1

A dependency version update is due.

Through centralized dependency management (Directory.Packages.props), the version only needs to be changed in one place.

QS-3.2

A CI build fails.

The error message is clear and understandable without contextual knowledge. The root cause can be narrowed down quickly.

QS-3.3

A new person takes over maintenance of the project.

Through standard tooling, automated pipelines, and the monorepo structure, onboarding into maintenance is possible without extensive training.

10.3.4. Usability

ID Scenario Notes

QS-4.1

An organization wants to post a volunteer opportunity for the first time.

The process is possible without training or a manual and is completed within a few minutes.

QS-4.2

A volunteer searches for opportunities in their area.

The search returns relevant results with a clear presentation of What, Where, and When - without an overloaded interface.

11. Risks and Technical Debt

The following table lists the relevant risks and technical debts. Each risk or technical debt links to the corresponding Technical Debt Record (TDR) with full context.

Table 13. Risks and technical debts
No. Context Description Status Date TDR

1

Rate Limiting

Missing rate limitation.

Resolved

2026-05-03

Rate Limiting

12. Glossary

Term Definition

ADR

Architecture Decision Record. A document that captures a significant architectural decision including its context, the decision itself, the rationale, considered alternatives, and consequences. ADRs are stored under docs/ADRs/.

AGPL

GNU Affero General Public License. The open-source license under which Einsatzbereit is released. Derivative works - including those deployed as network services - must be released under the same license.

arc42

A template for documenting software and system architectures, structured into 12 chapters. Widely used in German-speaking countries. See https://arc42.org.

CQRS

Command Query Responsibility Segregation. An architectural pattern that separates read operations (queries) from write operations (commands). In Einsatzbereit, implemented via MediatR in the Application layer.

EF Core

Entity Framework Core. The ORM (Object-Relational Mapper) used in the backend to interact with PostgreSQL. Manages the database schema via migrations.

Engagement

The act of a volunteer signing up to help with a specific volunteer opportunity. Modeled as an Engagement entity in the domain.

GHCR

GitHub Container Registry. The Docker image registry used to publish the frontend, backend, and Keycloak images on version releases.

IAM

Identity and Access Management. The discipline of managing who users are (authentication) and what they are allowed to do (authorization). Handled by Keycloak in Einsatzbereit.

JWT

JSON Web Token. A signed, compact token format used to carry authentication and authorization claims. The backend validates the JWT’s signature against Keycloak’s public JWKS keys on every request.

JWKS

JSON Web Key Set. A published set of public keys from Keycloak used by the backend to verify JWT signatures without contacting Keycloak on every request.

Keycloak

An open-source Identity and Access Management server. Used in Einsatzbereit for user authentication (OIDC), user management, and role-based access control.

MediatR

A .NET library implementing the Mediator pattern. Used in the Application layer to dispatch commands and queries to their respective handlers, decoupling the API layer from use case implementation.

NSwag

A .NET toolchain for generating API clients from OpenAPI specifications. The frontend TypeScript client (api-client.ts) is generated via NSwag and must never be hand-edited.

OIDC

OpenID Connect. An identity layer built on top of OAuth 2.0. Used for the authentication flow between the frontend, Keycloak, and the backend.

Organizer

A user with the organisator role. Represents a person who manages an organization’s volunteer opportunities. Test persona: Olaf (olaf / olaf123).

Organization

A club, NGO, or other entity that posts volunteer opportunities on the platform.

PKCE

Proof Key for Code Exchange. An extension to the OAuth 2.0 Authorization Code Flow that prevents authorization code interception attacks. Required for public clients (SPAs) where a client secret cannot be kept confidential.

Volunteer

A user who searches for and signs up for volunteer opportunities. Test persona: Vera (vera / vera123).

Volunteer Opportunity

A concrete request for help posted by an organization. Describes what is needed, where, when, and what skills are required. Core entity of the domain.