About arc42

arc42, the template for documentation of software and system architecture.

Template Version 8.2 EN. (based upon AsciiDoc version), January 2023

Created, maintained and © by Dr. Peter Hruschka, Dr. Gernot Starke and contributors. See https://arc42.org.


Note

This version of the template contains some help and explanations. It is used for familiarization with arc42 and the understanding of the concepts. For documentation of your own system you use better the plain version.

1. Introduction and Goals

1.1. Requirements Overview

The project aims to develop a full-stack web application for a game named YOVI, communicating human players and automated agents. The following high level specifications must be in the final version of the application:

1.1.1. User Management

ID Description

FR-01

The system shall allow users to register and authenticate (login/logout) to manage their personal profiles.

FR-02

The system shall maintain a persistent history of matches played by each registered user.

FR-03

The system shall provide a dashboard for users to view their statistics, including win/loss ratios and total games played.

1.1.2. Gameplay (Web Frontend)

ID Description

FR-04

The frontend shall implement the "Classic Version" of Game Y in a Player-vs-Machine (AI) mode.

FR-05

The system shall support variable board sizes, allowing the player to define the dimensions before starting a match.

FR-06

The UI shall allow the player to select from multiple game strategies or difficulty levels provided by the AI.

FR-07

The frontend shall visualize the board using the coordinate systems (Barycentric or Index-based) defined in the YEN notation.

1.1.3. Game Engine (Rust Module)

ID Description

FR-08

The module shall provide a web service interface to receive game states and return move calculations.

FR-09

The engine shall validate the current board state to determine if a match has been won, lost, or is still in progress.

FR-10

The engine shall implement at least two distinct move-generation strategies for the AI.

1.1.4. External Bot API

ID Description

FR-11

The API shall expose a play method that accepts a board state in YEN notation and returns the AI’s next move.

FR-12

The API shall provide endpoints for bots to retrieve user information and historical game data.

FR-13

The API shall support parameters for bots to specify which game strategy the engine should utilize during a match.

1.1.5. Data & Communication

ID Description

FR-14

All communication between the TypeScript frontend and the Rust backend shall be conducted via JSON messages.

FR-15

The system shall strictly adhere to the YEN notation for representing board layouts, player turns, and piece positions.

Contents

Short description of the functional requirements, driving forces, extract (or abstract) of requirements. Link to (hopefully existing) requirements documents (with version number and information where to find it).

Motivation

From the point of view of the end users a system is created or modified to improve support of a business activity and/or improve the quality.

Form

Short textual description, probably in tabular use-case format. If requirements documents exist this overview should refer to these documents.

Keep these excerpts as short as possible. Balance readability of this document with potential redundancy w.r.t to requirements documents.

Further Information

See Introduction and Goals in the arc42 documentation.

1.2. Quality Goals

Goal Description

Availability

The application and its API must be publicly accessible and maintain high uptime for both web users and bot integrations.

Usability

The frontend should be intuitive, allowing users to easily toggle between game strategies and view their statistics without a steep learning curve.

Performance

The backend architecture should handle concurrent matches from both web users and API-based bots without significant latency.

Security

User data and match histories must be protected via secure authentication, ensuring users can only manage their own profiles.

Contents

The top three (max five) quality goals for the architecture whose fulfillment is of highest importance to the major stakeholders. We really mean quality goals for the architecture. Don’t confuse them with project goals. They are not necessarily identical.

Consider this overview of potential topics (based upon the ISO 25010 standard):

Categories of Quality Requirements
Motivation

You should know the quality goals of your most important stakeholders, since they will influence fundamental architectural decisions. Make sure to be very concrete about these qualities, avoid buzzwords. If you as an architect do not know how the quality of your work will be judged…​

Form

A table with quality goals and concrete scenarios, ordered by priorities

1.3. Stakeholders

Contents

Explicit overview of stakeholders of the system, i.e. all person, roles or organizations that

  • should know the architecture

  • have to be convinced of the architecture

  • have to work with the architecture or with code

  • need the documentation of the architecture for their work

  • have to come up with decisions about the system or its development

Motivation

You should know all parties involved in development of the system or affected by the system. Otherwise, you may get nasty surprises later in the development process. These stakeholders determine the extent and the level of detail of your work and its results.

Form

Table with role names, person names, and their expectations with respect to the architecture and its documentation.

Role/Name Contact Expectations

Development team

yovi_en1a

To receive clear requirements and timely feedback on builds.

Players

N/A

To get an engaging application of the game that is stable and intuitive.

Evaluators

Archisoft

To ensure the architectural integrity between the frontend (TypeScript) and backend (Rust) via the YEN notation.

Micrati

N/A

To receive a functional prototype that meets all predefined success criteria.

2. Constraints

2.1. Technical Constraints

Technical constraints define the specific technologies and tools that must be used.

Constraint Description

Programming Languages

Frontend must be TypeScript. The core Game Y logic (win verification/suggestions) must be Rust.

Data Exchange

All subsystem communication must use JSON formatted according to the YEN notation (size, turn, players, layout).

Deployment & Runtime

The system must be containerized with Docker and run on an Ubuntu Linux environment.

External Connectivity

The system must expose a documented Web API accessible by third-party bots for automated gameplay.

2.2. Architectural Constraints

Architectural constraints are the high-level design requirements that dictate the system’s structure.

Constraint Description

Subsystem Decoupling

The system must be split into at least two distinct subsystems (Web App and Rust Module). They must remain independent and communicate only via web services.

Strategy Extensibility

The architecture must support multiple AI strategies and difficulty levels, selectable by the user or the bot via the API.

Multi-Coordinate Support

The system must handle both Barycentric (x,y,z) and Index-based (0…​n) coordinate systems, ensuring correct mapping between the UI and the Engine.

2.3. Organizational Constraints

Organizational constraints relate to the project management and academic requirements.

Constraint Description

Academic Framework

Must satisfy all criteria for the ASW assignment, including traceability and quality attributes.

Team Workflow

Mandatory use of Git for version control, featuring documented Code Reviews and Issue Tracking.

Documentation Standard

Architecture must be documented using the arc42 template and include Architectural Decision Records (ADRs).

Evaluation Metrics

The system must be evaluated on Availability and Observability (Monitoring) and Testing Coverage.

2.4. Conventions

Conventions are the rules agreed upon by the team to ensure consistency.

Convention Description

Language

English is the mandatory language for code, documentation, and the API.

API Documentation

All endpoints must be fully documented.

Modeling

Diagrams must follow UML standards and be rendered using software such as PlantUML.

Naming Conventions

Follow standard TypeScript (camelCase) and Rust (snake_case) style guides respectively.

3. Context and Scope

The YOVI_0 system (Game Y at UniOvi) is a distributed gaming platform designed to provide a competitive environment for both human players and automated agents. The system’s primary boundary lies between the user-facing web interface and the high-performance game logic engine implemented in Rust.

3.1. Business Context

The business context defines how YOVI_0 interacts with external entities. The system acts as a standardized provider for both human players and third-party bots, ensuring interoperability through the YEN notation.

context diagram
Communication Partner Inputs Outputs

Human Player

Account registration data, game moves via hexagonal UI, and selection of AI strategy.

Real-time board updates, personal performance statistics, and historical match records.

External Bots

RESTful API requests containing current board states in YEN notation.

Calculated next moves in YEN notation and game-state validation.

Micrati Developers / Admins

Infrastructure configuration, CI/CD scripts, and Docker management.

Application health metrics, observability logs, and test coverage reports.

External Domain Interfaces:

  • YEN Notation: The primary domain language. It is a JSON-based representation ensuring interoperability between any external subsystem.

  • Coordinate Systems: Supports both Barycentric (x,y,z) and Index-based coordinates to accommodate different mathematical approaches by bot developers.

3.2. Technical Context

The YOVI_0 architecture follows a microservices-inspired model. All communication between the React-based frontend and the specialized services is handled over network calls.

Interface Protocol Description

Client Browser

HTTPS / TCP

The entry point for the user. Delivers the React SPA, which subsequently handles business logic via fetch/axios.

Internal Services

HTTP / JSON

Communication between the Webapp and the Node.js User Service (Port 3000) and the Rust GameY Engine (Port 4000).

Public Bot API

REST / JSON

A public endpoint allowing third-party applications to interact with the game engine using the YEN standard.

Mapping Input/Output to Channels:

  • Game Logic Flow: Move submissions are sent via JSON POST to the Rust service. The service parses the YEN layout, validates the move, and returns the updated state.

  • Authentication Flow: Credentials are sent via HTTP POST to the User Service, which processes the persistence simulation and returns a status code.

  • Observability: Logs from Node.js and Rust are mapped to standard Docker output (stdout), accessible via the technical management console.

4. Solution Strategy

4.1. Technology Decisions

As outlined in the Technical Context (Section 3), the core technology stack and infrastructure—Rust for the Logic Engine, React.js for the Frontend, Node.js for the User Service, YEN Notation for communication, and Docker for containerization were predefined constraints for this project.

Our primary architectural decisions focus on how to integrate these given constraints effectively and what supplementary technologies to employ to complete the system:

Decision

Technology

Motivation

Database

MongoDB

Document-based storage naturally fits the predefined YEN Notation (JSON) format seamlessly and allows for flexible player statistics without rigid schemas.

4.2. Top-level Decomposition

To effectively integrate the mandated technologies, the system follows a Microservices-oriented decomposition. This ensures a clean separation of concerns and independent scalability:

  • Webapp (React): Serves as the presentation layer and the primary entry point for human users.

  • Logic Engine (Rust): A stateless, isolated service dedicated purely to high-performance game rule validation and AI calculations (Port 4000).

  • User Service (Node.js): Acts as the orchestrator for user accounts and statistics, handling concurrent API requests and communicating directly with our chosen MongoDB cluster (Port 3000).

4.3. Achievement of Quality Goals

  • Interoperability: By rigorously applying the mandated YEN Notation across our REST/JSON APIs, the system allows external bots (using different coordinate systems like Barycentric or Index) to integrate effortlessly with the Rust engine.

  • Persistence & Flexibility: Our strategic decision to use MongoDB ensures that as the game evolves (e.g., adding new bot metrics or match data), the system can dynamically adapt its data structures.

  • Performance: The architectural decoupling guarantees that the heavy computational hexagonal grid logic is strictly handled by the Rust Engine, while the Node.js service leverages its non-blocking I/O to handle user requests without bottlenecks.

5. Building Block View

The Building Block View provides a hierarchical decomposition of the YOVI_0 system. It describes the static structure, showing how the system is organized into subsystems and components, and how they interact with each other. This view is essential for understanding the overall architecture and the responsibilities of each part of the system.

5.1. Level 1: Overall System

Level 1 represents the highest level of abstraction, showing the main subsystems of the YOVI_0 system and their interactions. Each subsystem is responsible for a specific aspect of the system’s functionality, and they communicate with each other to fulfill the requirements of the project.

The following diagram shows the top-level decomposition of the YOVI_0 system into its three primary subsystems: the Frontend (Webapp), the User Management (User Service), and the Logic Engine (GameY).

level1 whitebox

5.1.1. Component Descriptions

Name Responsibility

Webapp

The central UI and gateway. Manages hexagonal grid rendering and provides the documented API for external bots.

User Service

Handles administrative logic: user registration, session management, and persists match statistics to the DBMS.

GameY Engine

The high-performance "brain." Written in Rust for memory safety and speed; it validates game rules and provides AI moves via YEN notation.

MongoDB

The Document-based DBMS. It persists all non-transient data, chosen for its native support of JSON-like structures (perfect for YEN payloads).

5.2. Level 2: Webapp (Frontend Subsystem)

The Webapp is a Single Page Application (SPA) built with React and Vite. It acts as the primary user interface and the orchestrator of requests between the User Service and the GameY Engine.

webapp level2

5.2.1. Component Descriptions

Component Detailed Responsibility

main.tsx

The Bootstrap of the application. It utilizes the react-dom/client library to find the root element in the HTML and injects the React application. It implements StrictMode to identify potential problems during development.

App.tsx

The Layout Orchestrator. It imports the global CSS and provides the high-level UI structure. It acts as a container for the different views (currently the RegisterForm).

RegisterForm.tsx

The Interaction Hub. This is the most complex component in this module. It manages local state for input data, loading animations, and error handling. It is responsible for the sequence: Submit → User Creation → Game Status Check.

env.d.ts

The Configuration Schema. It defines the ImportMetaEnv interface. This ensures that the TypeScript compiler recognizes custom environment variables used for service discovery, preventing runtime crashes.

5.2.2. Internal dynamics and logic

The internal behavior of this module is driven by the state within RegisterForm.tsx:

  1. Service Discovery: The module does not hardcode URLs. It uses an Environment-Aware approach:

  2. Asynchronous Lifecycle:

    • User Registration: Initiates a fetch POST request with a JSON payload containing the username.

    • Chained Validation: Upon a successful (200 OK) response from the User Service, it triggers the checkGamey() function. This ensures that the player is only notified that "Game is ready" if the Rust engine is reachable.

  3. Resilience: The UI is designed to be fail-safe. If the GameY engine is down, the user is still successfully registered, but the system displays a "Game is not ready" warning to manage user expectations.

5.3. Level 2: GameY Engine (Logic Subsystem)

The GameY Engine is a high-performance Rust subsystem responsible for the rules of the "Game of Y". It is structured as both a Library (lib.rs) for core logic and a Binary (main.rs) that provides a Command-Line Interface (CLI) and an HTTP Bot Server.

gamey level2

5.3.1. Component Descriptions

Module Detailed Responsibility

main.rs

Application Entry Point. Uses clap to parse CLI arguments. It determines the execution mode: Human (local CLI), Computer (local vs Bot), or Server (HTTP API for the Webapp).

lib.rs

Library Root. The central exported interface. It organizes the crate into public modules and provides the high-level GameY struct used to manipulate the triangular board.

core

The Rules Engine. Implements the triangular board mathematics, coordinate systems (Barycentric/Index), and the connection-based win conditions.

bot_server

The Gateway. Uses tokio to run an asynchronous HTTP server. It allows the Webapp to request moves via REST, serving as the bridge between the React frontend and the Rust logic.

bot

The Intelligence. Contains the GamerBot and the YBotRegistry. It implements the strategies used to calculate the next optimal move for a computer player.

notation

The Interoperability Layer. Implements YEN (Y Exchange Notation). It defines a JSON-serializable format for board layouts (e.g., "B/BR/.R."), inspired by chess’s FEN.

cli

Interactive Shell. Provides a rich terminal experience using rustyline. It supports board rendering, move history, and saving/loading game states to files.

gamey_error

Domain Safety. Defines the GameYError enum using thiserror. It strictly enforces game rules (e.g., Occupied, InvalidPlayerTurn) and ensures system resilience.

5.3.2. Internal dynamics and logic

The GameY module operates through distinct execution patterns:

  1. Stateful CLI Loop: In cli.rs, the run_cli_game function maintains an interactive loop. It captures user indices (e.g., "5"), converts them to coordinates, and applies moves to the GameY state. It supports "meta-commands" like save, load, and show_coords.

  2. Stateless Server Pattern: When running in Mode::Server, the engine becomes a stateless API. It receives a YEN payload from the Webapp, reconstructs the game state momentarily in memory, calculates the AI’s response via the bot module, and returns the new state.

  3. Strict Error Enforcement: Every action passes through the gamey_error module. If a player (or the Webapp) attempts an illegal move (such as placing a piece on an Occupied cell), the engine returns a specific error variant rather than allowing an inconsistent game state.

  4. Serialization (YEN): The notation/yen.rs module ensures that complex triangular board states can be compressed into a single string. This is critical for the "Building Block" connection between the Webapp and GameY, as it minimizes the data payload sent over HTTP.

5.4. Level 2: User Service

user service level3

5.4.1. Component Responsibilities

Component Technology Responsibility

Express Entry Point

Node.js / Express 5.x

Orchestrates the business logic for /createuser.

Security Manager

bcrypt

Ensures "Security by Design" by hashing passwords.

Database Driver

MongoDB Driver 7.x

Handles asynchronous communication with the yovi database.

Metrics Provider

express-prom-bundle

Bridges the application to the Prometheus monitoring instance.

6. Runtime View

6.1. Scenario 1: Human Player vs. AI (Move Execution)

Description: This scenario illustrates the core game loop when a human player interacts with the frontend to play against the system’s AI. It highlights the transformation of UI interactions into the standardized YEN notation and the delegation of logic to the high-performance Rust engine.

Notable Aspects: The Webapp acts as a pure presentation layer. It does not calculate game rules. All coordinate conversions (Barycentric/Index) and move validations are strictly handled by the GameY Engine.

human vs ai move

6.2. Scenario 2: Human Player vs. Human Player (Multiplayer Turn Execution)

Description: This diagram illustrates the turn flow between two human players. It demonstrates how a move made by one player is validated, saved, and seamlessly pushed to the opponent’s screen.

Notable Aspects: Unlike the "Human vs. AI" scenario where the Rust engine immediately calculates a counter-move, here the GameY Engine (Rust) is strictly used for rule validation. The User Service (Node) acts as the central state manager. It handles saving the updated board to the database internally and directly pushes the new state to the second player’s client (via WebSockets/Push), initiating their turn without the need for manual retrieval or polling.

human vs human

6.3. Scenario 3: Match Conclusion and Statistics Persistance

Description: This scenario demonstrates the data flow when a game concludes (either by a win, loss, or draw). It shows the interaction between the Frontend, the Logic Engine, and the User Service to ensure persistent data storage.

Notable Aspects: The GameY Engine is stateless; it only validates the win. The responsibility of saving the match and updating user statistics is delegated to the User Service, which asynchronously communicates with MongoDB.

match conclusion

6.4. Scenario 4: User Authentication and Login Flow

Description: This scenario illustrates the security and session management architecture of the system. It details how the system handles a user login request, verifies credentials, and establishes a secure session for the player.

Notable Aspects: The GameY Engine is bypassed entirely for this process, as it is strictly dedicated to game logic. This interaction occurs purely between the Webapp (Frontend), the User Service (Node.js), and the Database (MongoDB). It demonstrates a clean separation of concerns where the User Service handles all identity and access management.

auth flow

6.5. Scenario 5: Error Handling - Invalid Move Validation

Description: This exception scenario demonstrates system resilience. It shows what happens when an invalid move (for example, attempting to play on an already occupied coordinate) is submitted by the user.

Notable Aspects: The GameY Engine acts as the single source of truth for game rules. If a YEN payload violates these rules, the engine strictly rejects the state change. It returns an appropriate error code, which the Webapp must gracefully handle to warn the user without breaking or crashing the UI state.

invalid move

7. Deployment View

7.1. Infrastructure Level 1: Azure Cloud Environment

7.1.1. Motivation

The system runs on a single Azure Virtual Machine (Ubuntu 24.04 LTS). Azure was chosen for its reliability and easy VM setup. A single VM keeps costs low while still resembling a real production environment. All components are containerized with Docker so that the setup works the same way in development and in production, and deployments via GitHub Actions stay simple.

level1 whitebox

7.2. Infrastructure Level 2: Container Orchestration (Docker Compose)

7.2.1. Motivation

Docker Compose manages all containers in a single configuration file. All services run on a shared internal network (monitor-net) so they can talk to each other without exposing unnecessary ports to the outside. The Webapp is compiled with the backend URLs baked in at build time (VITE_API_URL, VITE_GAMEY_URL), so no extra runtime configuration is needed.

The diagram below shows how containers are connected inside monitor-net. Grafana maps its internal port 3000 to host port 9091 to avoid clashing with the Users service.

level2 docker

7.3. Mapping of Building Blocks to Infrastructure

Building Block Infrastructure Element Description

webapp

Docker Container (Nginx)

Serves the React/Vite frontend. Accessible via Port 80.

users

Docker Container (Node.js)

Handles identity, history, and stats. Accessible via Port 3000.

gamey

Docker Container (Rust)

Logic for Game Y moves and win validation. Accessible via Port 4000.

mongodb

Docker Container (MongoDB)

Persistent document store for user profiles and match history. Accessible internally on Port 27017.

prometheus

Docker Container

Scrapes metrics from the services via the internal network.

grafana

Docker Container

Visualizes metrics. Mapped to Port 9091 to avoid conflict with the Users service.

7.4. Infrastructure Level 3: Data Persistence

7.4.1. Motivation

The application requires its data to survive when containers restart. Prometheus and Grafana use bind mounts so their configuration files live directly in the repository and are version-controlled like any other code. MongoDB uses a named Docker volume so that user and game data persists across docker-compose down and up cycles without any manual intervention.

Element Storage Strategy Path

Metrics Config

Docker Bind Mount

./users/monitoring/prometheus/etc/prometheus

Grafana Dashboards

Docker Bind Mount

./users/monitoring/grafana/provisioning/etc/grafana/provisioning

User & Game Data

Docker Named Volume (mongodb_data)

Managed by Docker. Data survives restarts and redeployments independently of the container image.

7.5. Network and Connectivity

All containers communicate over the monitor-net bridge network. Only the following ports are exposed to the host:

  • Port 80: Web application entry point.

  • Port 3000: Users REST API (used by Webapp and Bots).

  • Port 4000: Game Engine API (YEN notation).

  • Port 27017: MongoDB — internal only, not exposed to the host.

  • Port 9090 / 9091: Prometheus and Grafana for system observability.

8. Cross-cutting Concepts

8.1. Domain Concepts

8.1.1. Game Y and Hexagonal Grids

The core domain of the application revolves around the "Classic Version" of Game Y. The game environment is based on variable-sized hexagonal boards. The system supports multiple coordinate representations for these grids: * Barycentric Coordinates (x,y,z): Used to represent three-dimensional positioning in a 2D hexagonal space. * Index-based Coordinates (0…​n): Linear representation for simpler indexing in arrays or matrices.

8.1.2. YEN Notation

All game states are uniformly formatted using the YEN Notation, which dictates how board sizes, player turns, and piece positions are serialized. This ensures consistent state representation across the Frontend, the Logic Engine, and external bots.

A YEN string encodes the complete game state in a compact, human-readable format. For example, on a 3×3 board where Blue has played two cells and Red has played one:

B/BR/.R.
  • B — It is Blue’s turn.

  • BR/ — Row 1 contains a Blue piece, a Red piece, then the row separator.

  • .R. — Row 2 contains an empty cell, a Red piece, and another empty cell.

8.2. Architecture and Design Patterns

8.2.1. Microservices Architecture

The concrete service breakdown (Webapp, User Service, Logic Engine) is described in Sections 4 and 5. The cross-cutting design rules that govern the microservice decomposition are:

  • Independent Deployability: Each service is packaged as its own Docker image with an isolated build pipeline. A new release of one service never requires redeploying another.

  • Strict Network Boundaries: Services communicate exclusively over defined HTTP endpoints. There are no shared databases, in-process calls, or file-system dependencies between services.

  • Single Responsibility: Each service owns exactly one concern — the Logic Engine owns game rules, the User Service owns identity and persistence, and the Webapp owns presentation. Business logic must not leak across service boundaries.

8.2.2. Stateless Processing

The Logic Engine is intentionally stateless. Current game states (in JSON format) are passed within each request, allowing the engine to calculate AI behavior or determine win/loss states without storing active match sessions in memory.

8.3. Communication and Integration Concepts

8.3.1. RESTful JSON APIs

Communication both internally (between subsystems) and externally (third-party bots) relies fully on HTTP REST APIs utilizing JSON. * Internal APIs: The User Service and Logic Engine communicate with the Webapp using predefined JSON schemas strictly validating YEN notation. * External Bot Interface: The system provides dedicated endpoints (e.g., a play method) for third-party bots to interact with the engine.

8.3.2. Asynchronous Push Communication (WebSockets)

For real-time interactions, particularly in the "Human vs. Human" multiplayer scenario, the architecture envisions asynchronous push communication. Instead of relying on inefficient client-side polling, the Node.js User Service will actively push game state updates (e.g., opponent moves) directly to the connected React clients via WebSockets. * Current State: Asynchronous push communication is planned but not yet implemented. The current system relies exclusively on RESTapi calls. * Future Updates: Once WebSockets (e.g., via Socket.IO) are integrated, this section will be expanded with the specific event structures and network flow diagrams.

api communication flow

8.4. Data Persistence Concepts

8.4.1. Data Mapping Strategy

The technology choice (MongoDB) is documented in Sections 4 and 7. The cross-cutting design rule for persistence is how domain relationships are mapped to documents:

  • User Documents are stored as flat, self-contained documents in the users collection (fields: username, email, password hash, createdAt). No embedding of child objects is used at this stage.

  • Match History (planned): Match results will be stored as separate documents in a matches collection, referencing the participating users by their _id rather than embedding the full user object. This avoids data duplication and keeps user updates (e.g., profile changes) consistent without cascading writes.

  • Design Rule — Referencing over Embedding: Whenever two entities have independent lifecycles (e.g., a user exists regardless of any single match), the system favours document references (ObjectId foreign keys) over nested embedding. Embedding is reserved for data that is never queried or updated independently (e.g., a list of coordinates within a single match snapshot).

8.5. Security Concepts

8.5.1. User Authentication and Password Storage

  • Registration: Players register with a username, email, and password. The User Service hashes all passwords using bcrypt (cost factor 10) before persisting them to MongoDB. Plaintext passwords are never stored.

  • Login: Upon login the User Service retrieves the stored hash and verifies it against the submitted password via bcrypt.compare.

8.5.2. Session Management

  • Current State: Token-based session management (e.g., JWTs) is not yet implemented. The runtime scenario in Section 6.4 already envisions a JWT-based flow (generate token on login → store in Session Storage → attach to subsequent requests). This will be implemented in a future iteration and this section will be updated accordingly.

  • Planned Approach: The User Service will issue a signed JSON Web Token (JWT) upon successful login. The React Webapp will store the token in the browser’s Session Storage and attach it as an Authorization: Bearer <token> header on every API request. The User Service will validate the token on protected endpoints.

8.5.3. Configuration and Secrets Management

Service configuration (ports, upstream URLs, database connection strings) is managed through environment variables that are injected via docker-compose.yml.

Variable Service Example Value

MONGODB_URI

User Service

mongodb://mongodb:27017/yovi

GAMEY_RUST_URL

Game API

http://gamey:4000

VITE_API_URL

Webapp (build-time)

http://localhost:3000

ALLOWED_ORIGINS

User Service

http://localhost,http://webapp

Warning

The current setup uses plain environment variables in docker-compose.yml, which is sufficient for development but not production-ready for sensitive values (e.g., database credentials). Migration to Docker Secrets or a vault-based solution is planned for the production hardening phase. This section will be updated once the approach is finalized.

8.5.4. Data Scoping and Privacy

  • Data Privacy: Requests are secured to ensure players can only access and modify their own personal profiles and match histories.

8.5.5. CORS (Cross-Origin Resource Sharing)

Because the Webapp (Port 80) communicates with backend APIs on different ports (3000, 3001, 4000), CORS must be configured explicitly.

  • User Service (Node.js): Implements a strict origin whitelist using the cors middleware. Allowed origins are configured via the ALLOWED_ORIGINS environment variable (comma-separated). By default, only localhost origins are permitted. Requests from unlisted origins are rejected with an error.

  • Game API (gameyapi): Currently uses a permissive CORS policy (cors() with no origin restriction) to facilitate external bot integration. This will be tightened before production deployment.

8.5.6. Rate Limiting

Note

Rate limiting is not yet implemented. Since the system exposes a public API for external bots (see Section 3), it is susceptible to abuse or accidental overload. Rate limiting middleware (e.g., express-rate-limit on the Node.js services or request throttling via an Nginx reverse proxy) is planned. This section will be updated once the strategy is finalized.

8.6. User Experience (UX) Concepts

8.6.1. State Management and Rendering

In the Frontend Webapp, complex match states and user actions are managed reactively. * State Trees: React manages the active game properties (board layout, opponent type, current turn) locally to provide instant visual feedback without blocking for server responses during non-validating actions. * Hexagonal UI Representation: The UI seamlessly maps the engine-provided mathematical coordinate arrays (Barycentric or Index-based) onto visual hexagonal grids for intuitive gameplay.

8.7. Quality and Reliability Concepts

8.7.1. Logging Strategy

All services emit logs exclusively to stdout/stderr, which allows the Docker container runtime to collect and forward them transparently. No dedicated log-aggregation sidecar is required for the current setup.

  • Rust Logic Engine (gamey): Uses the tracing crate with tracing_subscriber. This produces structured, level-based log output (INFO, DEBUG, WARN) that is machine-readable and can be forwarded to an aggregator (e.g., Loki/Grafana) in a future step. Fatal startup errors are written to stderr via eprintln!.

  • Node.js Services (users, gameyapi): Use the built-in console.log / console.warn / console.error API. Output is written directly to the process stdout/stderr, which Docker captures. Log lines are prefixed with context tags (e.g., [CREATE], [MOVE], [BOT]) to aid filtering.

  • React Frontend (webapp): Browser console.* calls are available during development. No log forwarding to the backend occurs from the client.

Note

Centralized log aggregation (e.g., shipping Docker logs to a Loki stack alongside the existing Prometheus/Grafana setup) is planned for a later iteration.

8.7.2. Error Handling and Cross-Service Error Propagation

The system uses a layered error propagation model based on standard HTTP semantics. The example described in Scenario 5 (Section 6.5) illustrates a concrete instance of this pattern.

error propagation

The concrete error handling layers are:

  • Rust Logic Engine: Returns precise HTTP error codes (400 Bad Request for invalid YEN/rule violations, 500 Internal Server Error for unexpected failures). The JSON body contains a machine-readable error field.

  • Node.js Middleware (Game API / User Service): Catches errors from upstream Rust calls, logs them via console.error, and maps them to sanitized, client-facing JSON responses. Internal error details (stack traces, Rust error messages) are not forwarded to the browser.

  • React Frontend: Reads HTTP status codes from API responses. Non-2xx responses trigger UI-level feedback (e.g., warning toasts, reverting optimistic state updates). The Webapp never crashes on expected error payloads.

8.7.3. Observability and Monitoring

To satisfy availability evaluation metrics, the system incorporates rigorous operational monitoring: * Metrics Ingestion: Both the Node.js API and the Rust Gamey Engine emit structured operational metrics. * Visualization: Prometheus scrapes system health, latency, and throughput metrics, which are then aggregated and visualized using Grafana dashboards.

8.7.4. Testing and Quality Assurance

System reliability is continuously verified through multiple layers of testing: * Multi-Layer Testing: The system utilizes unit tests for individual algorithmic checks (especially Rust logic), integration tests for API endpoints, and End-to-End (E2E) UI tests for critical user journeys. * Static Analysis: Code quality and security are strictly evaluated via SonarCloud against defined Quality Gates prior to any merge.

8.7.5. Continuous Integration and Deployment (CI/CD)

The development pipeline is automated natively with GitHub Actions: * CI Pipelines: Push events and pull requests trigger automated test suites and SonarCloud evaluations. * CD Pipelines: Upon a successful release merge, Docker images are automatically built from each service’s Dockerfile and orchestrated on the production server via docker-compose (see Sections 2 and 7 for the containerization details).

8.8. Development and Operational Concepts

8.8.1. Documentation Strategy

The architecture documentation follows a strict Docs-as-Code approach: * AsciiDoc & Arc42: All architectural documentation is written in AsciiDoc, structured entirely according to the arc42 template. This approach ensures technical documentation lives alongside the source code in version control. * PlantUML: As dictated by our conventions, all architectural diagrams and models must comply with UML standards and are rendered programmatically using PlantUML.

8.8.2. Collaboration and Source Control

  • Git Workflows: Employs pull requests, mandatory code reviews, and issue tracking.

  • Traceability: Documentation must constantly be maintained following the arc42 structure (including ADRs) to comply with academic quality evaluation criteria.

9. Architecture Decisions

Contents

Important, expensive, large scale or risky architecture decisions including rationales. With "decisions" we mean selecting one alternative based on given criteria.

Please use your judgement to decide whether an architectural decision should be documented here in this central section or whether you better document it locally (e.g. within the white box template of one building block).

Avoid redundancy. Refer to section 4, where you already captured the most important decisions of your architecture.

Motivation

Stakeholders of your system should be able to comprehend and retrace your decisions.

Form

Various options:

  • ADR (Documenting Architecture Decisions) for every important decision

  • List or table, ordered by importance and consequences or:

  • more detailed in form of separate sections per decision

Further Information

See Architecture Decisions in the arc42 documentation. There you will find links and examples about ADR.

10. Quality Requirements

Content

This section contains all quality requirements as quality tree with scenarios. The most important ones have already been described in section 1.2. (quality goals)

Here you can also capture quality requirements with lesser priority, which will not create high risks when they are not fully achieved.

Motivation

Since quality requirements will have a lot of influence on architectural decisions you should know for every stakeholder what is really important to them, concrete and measurable.

Further Information

See Quality Requirements in the arc42 documentation.

10.1. Quality Tree

Content

The quality tree (as defined in ATAM – Architecture Tradeoff Analysis Method) with quality/evaluation scenarios as leafs.

Motivation

The tree structure with priorities provides an overview for a sometimes large number of quality requirements.

Form

The quality tree is a high-level overview of the quality goals and requirements:

  • tree-like refinement of the term "quality". Use "quality" or "usefulness" as a root

  • a mind map with quality categories as main branches

In any case the tree should include links to the scenarios of the following section.

10.2. Quality Scenarios

Contents

Concretization of (sometimes vague or implicit) quality requirements using (quality) scenarios.

These scenarios describe what should happen when a stimulus arrives at the system.

For architects, two kinds of scenarios are important:

  • Usage scenarios (also called application scenarios or use case scenarios) describe the system’s runtime reaction to a certain stimulus. This also includes scenarios that describe the system’s efficiency or performance. Example: The system reacts to a user’s request within one second.

  • Change scenarios describe a modification of the system or of its immediate environment. Example: Additional functionality is implemented or requirements for a quality attribute change.

Motivation

Scenarios make quality requirements concrete and allow to more easily measure or decide whether they are fulfilled.

Especially when you want to assess your architecture using methods like ATAM you need to describe your quality goals (from section 1.2) more precisely down to a level of scenarios that can be discussed and evaluated.

Form

Tabular or free form text.

11. Risks and Technical Debts

Contents

A list of identified technical risks or technical debts, ordered by priority

Motivation

“Risk management is project management for grown-ups” (Tim Lister, Atlantic Systems Guild.)

This should be your motto for systematic detection and evaluation of risks and technical debts in the architecture, which will be needed by management stakeholders (e.g. project managers, product owners) as part of the overall risk analysis and measurement planning.

Form

List of risks and/or technical debts, probably including suggested measures to minimize, mitigate or avoid risks or reduce technical debts.

Further Information

See Risks and Technical Debt in the arc42 documentation.

12. Glossary

Contents

The most important domain and technical terms that your stakeholders use when discussing the system.

You can also see the glossary as source for translations if you work in multi-language teams.

Motivation

You should clearly define your terms, so that all stakeholders

  • have an identical understanding of these terms

  • do not use synonyms and homonyms

Form

A table with columns <Term> and <Definition>.

Potentially more columns in case you need translations.

Further Information

See Glossary in the arc42 documentation.

Term Definition

<Term-1>

<definition-1>

<Term-2>

<definition-2>