Skip to content
CAI
Software that uses CAICheck a score

marein/php-gaming-website

51.8

Adequate · 21 September 2026

12.9k

lines of production code

PHP

with JavaScript

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is a PHP-based gaming platform built on Symfony 7 and PHP 8.5, featuring a modernized architecture with a command/query bus, event sourcing, and a shared common library. It currently supports a fully implemented Connect Four game with real-time updates, alongside a functional Chat service and a Memory game domain. The platform provides user identity management, browser push notifications, and load-testing infrastructure, all wrapped in a responsive web interface.

How it got here

2017–2019 — Domain-driven architecture and modernization

54 changes.

The project underwent a significant architectural shift, removing legacy Symfony infrastructure in favor of a modernized, domain-driven structure with a new message bus and event sourcing capabilities. This period focused on implementing core features for Chat, Connect Four, and Identity modules using this new pattern, while also introducing a Memory game domain. The work included extensive refactoring of the codebase to support these new domains and added comprehensive unit and acceptance tests.

2020–2024 — infrastructure modernization and Connect Four implementation

33 changes.

This period focused on modernizing the application's core infrastructure, including a PHP 8.5 upgrade, a kernel refactoring, and the introduction of a common library with features like a fork pool, scheduler, and event store. Concurrently, the project implemented the Connect Four game logic, real-time chat, and a client-side page engine, supported by comprehensive load testing and automated database migrations.

2025–2026 — Platform infrastructure and UI expansion

17 changes.

This period focused on establishing core infrastructure for game logic and user management, including a new timer subsystem, username caching, and RPC-based chat handling. Simultaneously, the project expanded its user-facing features by introducing the Connect Four game interface, authentication flows, and shared UI components like pagination and alerts.

Features

Add Doctrine, Predis, and Symfony integrations for the Event Store

The Event Store now includes concrete implementations for persisting and tracking events using Doctrine DBAL, Predis, and Symfony Console. Users can store domain events in a relational database via the new DoctrineEventStore, which supports stream-based queries, batch appends, and cleanup operations. The system also introduces EventStorePointer implementations for MySQL (Doctrine) and Redis (Predis) to track the most recent published event, enabling safe log compaction and streaming. Additionally, Symfony console commands are provided to follow the event stream and perform safe cleanup of old events based on pointer values.

src/Common/EventStore/Integration · high confidence

Add Doctrine-based chat persistence implementation

Introduces DoctrineChatGateway, a new infrastructure component that persists chat data to a relational database using Doctrine DBAL. This implementation supports creating chats, writing messages with idempotency keys, and querying message history, effectively providing the concrete storage layer for the chat application.

src/Chat/Infrastructure · high confidence

Add alert, icon, and username display macros

The templates/macro directory now includes three new Twig macros to support the frontend. The alert macro renders styled notification boxes with optional icons and background color overrides. The icons macro provides SVG definitions for danger, warning, success, and info states. The username macro renders a user's display name, splitting the local part from the global ID tag. These additions enable consistent alert styling and username rendering across the application.

templates/macro · high confidence

Add common timer infrastructure for game and move timeouts

The src/Common/Timer directory introduces a new timer subsystem. This includes a Timer interface with GameTimer and MoveTimer implementations, a TimeoutService for managing timeout events, and a PredisTimeoutStore for persistence. Additionally, a HandleTimeoutsCommandTemplate is added to parallelize timeout handling via a ForkPool, exposing Prometheus metrics. This provides the foundational components for handling game and move timeouts.

src/Common/Timer · high confidence

Add periodic heartbeat middleware for Doctrine connections

A new Doctrine middleware (SchedulePeriodicHeartbeatMiddleware) and its supporting classes (ScheduleHeartbeatOnConnectDriver, ConnectionHeartbeatHandler, TrackActivityConnection) have been added to the Common library. This feature automatically schedules periodic dummy SQL queries on active database connections to keep them alive, with the heartbeat logic only active in CLI environments.

src/Common/DoctrineHeartbeatMiddleware · high confidence

Add player search statistics query

Introduced a new query handler and supporting classes (PlayerSearchStatisticsHandler, PlayerSearchStatisticsQuery, PlayerSearchStatisticsResponse) that retrieve game statistics for a specific player. When a playerId is provided, the system fetches the player's game statistics; otherwise, it returns a zeroed-out map of game states.

src/ConnectFour/Application/Game/Query/PlayerSearchStatistics · high confidence

Add reusable pagination component

A new \pagination.html.twig\ template has been added to the \templates/include\ directory. This component provides a reusable pagination UI that renders page links with support for ellipsis, active state highlighting, and configurable query parameters, enabling consistent pagination across the site.

templates/include · high confidence

Added RPC message handler for chat operations

A new RpcMessageHandler has been introduced in the chat presentation layer to process incoming messages. This handler routes 'InitiateChat' and 'WriteMessage' requests to their respective command handlers, enabling the system to process chat initiation and message sending via RPC.

src/Chat/Presentation/Messaging · high confidence

Added idempotent storage abstraction and implementations

A new idempotent storage system has been introduced to ensure that operations, such as initiating chats, are executed exactly once. This includes an \IdempotentStorage\ interface and two concrete implementations: an in-memory store for simple scenarios and a Redis-backed store using Predis for distributed environments, both supporting concurrent-safe storage of idempotency keys.

src/Common/IdempotentStorage · high confidence

Added load-test scenarios for Connect Four gameplay

New k6 load-test scripts have been added to the deploy/load-test/scenario directory. The go-to-page.js script simulates repeated HTTP GET requests to a specified page, while play-connect-four.js simulates a full Connect Four game session, including opening a game, joining as a second player, and executing a sequence of moves. These scripts enable automated performance testing of the Connect Four feature.

deploy/load-test/scenario · high confidence

Added load-testing infrastructure and configuration

A new deployment stack for load testing has been introduced, comprising environment variables for application configuration, service definitions for observability (Grafana, Prometheus, node-exporter), a ProxySQL sidecar for database routing, RabbitMQ for messaging, and Traefik for HTTPS termination and HTTP-to-HTTPS redirection.

deploy/load-test/stack · high confidence

Added login and signup forms and controllers

Introduced new HTTP controllers and form types for user authentication and registration. The LoginController and SignupController handle the login flow (sending magic links) and the multi-step signup process (email verification and username confirmation). Corresponding Symfony form classes (LoginType, SignupType) define the input fields and validation. Twig templates provide the UI for the login page, the 'check inbox' screen, and the three-step signup flow (get started, verify email, confirm).

src/Identity/Port/Adapter/Http · high confidence

Added public entry point and browser assets

The application now exposes a PHP entry point at public/index.php to handle requests, alongside new browser manifest and icon assets (site.webmanifest, safari-pinned-tab.svg) to support PWA features and browser tabs.

public · high confidence

Configure Connect Four game module

The Connect Four game module is now fully configured with dedicated routing for lobby, history, and game actions, along with service definitions, database migrations, and frontend asset mappings. This establishes the necessary infrastructure for the game to function within the application.

config/connect-four · high confidence

Expose Prometheus metrics via HTTP endpoints

Added new components to expose application metrics in Prometheus format. A new \ExposeMetricsTask\ provides a standalone HTTP server for metrics, while the Symfony integration adds a \CollectMetricsListener\ to track HTTP request durations, request counts, and exceptions, alongside a \MetricsController\ to serve the rendered metrics data.

src/Common/ForkPool/Integration, src/Common/SymfonyPrometheus · high confidence

Expose bot registration and lookup via messaging

The system now supports registering bots and looking them up by username through the message broker. A new \RpcMessageHandler\ processes \RegisterBot\ and \GetBotByUsername\ messages, routing them to the corresponding application commands and queries, while a new \PublishDomainEventsToMessageBrokerSubscriber\ publishes user-related domain events to the message broker.

src/Identity/Port/Adapter/Messaging · high confidence

Initial database schema and event store migrations for identity and event sourcing

The application's database schema is established through new Doctrine migrations. The first migration creates the core identity tables: an 'account' table (with id, type, version, and username), a 'bot' table, and a 'user' table, each linked to the account. A subsequent migration initializes the event store schema using the shared 'Gaming\\Common\\EventStore\\Integration\\Doctrine\\DoctrineEventStoreSchema' class, and a third migration sets up the event store pointer table. These changes provide the necessary persistence structures for user, bot, and event-driven architecture.

src/Identity/Port/Adapter/Persistence/Migration · high confidence

Introduce ChatController for HTTP endpoints

A new ChatController has been added to handle HTTP requests for the chat feature. It exposes endpoints to write messages and retrieve message history, utilizing a command bus for writes and a query bus for reads, while leveraging the security layer to identify the current user.

src/Chat/Presentation/Http · high confidence

Introduce ChatService for chat application logic

Added ChatService, ChatGateway interface, and ChatId value object to handle chat operations. The ChatService manages chat initiation and message writing, utilizing an EventStore for domain events and an IdempotentStorage to ensure chats are initiated exactly once. The ChatGateway interface defines methods for creating chats, writing messages, and retrieving chat data, while ChatId encapsulates UUID v6 generation and validation.

src/Chat/Application · high confidence

Introduce Connect Four game implementation

Adds a complete Connect Four game implementation, including a game board with move history and winning sequence highlighting, player status indicators, a game list for open games, and interactive buttons for aborting and resigning with confirmation dialogs. The feature includes real-time updates via Server-Sent Events, a timer with panic-level sound effects, and an animated game replay on hover.

assets/js/ConnectFour · high confidence

Introduce Connect Four game interface

Adds the complete HTTP view layer for the Connect Four game, including the game board, lobby, history, and challenge pages. The new templates render player names, game states, and timers, and integrate with custom web components for the interactive board and chat.

src/ConnectFour/Port/Adapter/Http/View · high confidence

Introduce ForkPool for parallel task execution

A new ForkPool component has been added to the common library, providing a mechanism to fork and manage background processes. The implementation includes a Task interface and a ForkPool class that handles process creation, signal handling, and process lifecycle management (wait, kill, and signal forwarding). This enables applications to run tasks in parallel child processes with structured communication channels.

src/Common/ForkPool · high confidence

Introduce a new message bus architecture with multiple routing strategies

The codebase now includes a new message bus implementation in the \src/Common/Bus\ directory. This introduces a \Bus\ interface for handling requests, alongside several concrete implementations: \PsrCallableRoutingBus\ for simple callable routing, \PsrCompiledRoutingBus\ for pre-compiled routes, and \PsrRuntimeRoutingBus\ for runtime discovery. Additionally, a \HandlerDiscovery\ class enables automatic service discovery, and a \RetryBus\ wrapper provides configurable retry logic. A \TestContainer\ is also provided for testing purposes.

src/Common/Bus · high confidence

Introduce application services for user, account, and bot identity management

Added new application-layer services and their associated commands, queries, and response models to handle identity operations. The \UserService\ manages user lifecycle (arrival, sign-up, and lookup by ID or email), the \AccountService\ retrieves usernames for a list of account IDs, and the \BotService\ handles bot registration and username-based lookup. These changes introduce the core application logic for managing users, accounts, and bots within the identity system.

src/Identity/Application · high confidence

Introduce chat command and query objects

Added new command and query classes to the chat application layer. InitiateChatCommand and WriteMessageCommand encapsulate the data required to start a new chat and send messages, respectively. Additionally, the MessagesQuery class was introduced to retrieve chat messages with pagination support (offset and limit). These changes establish the interface for interacting with the chat system's application logic.

src/Chat/Application/Command · high confidence

Introduce chat service configuration and API routes

The chat feature is now configured with dedicated service definitions, a Doctrine DBAL connection for the chat database, and API routes for sending and retrieving messages. This establishes the backend infrastructure for the chat module, including the import map for the chat widget and migration paths for database schema updates.

config/chat · high confidence

Introduce client-side page engine for dynamic navigation and form handling

Added a new JavaScript module (assets/js/app.js and assets/js/pe.js) that implements a client-side page engine. This engine intercepts standard browser navigation and form submissions, replacing full page loads with dynamic content updates. It provides features such as lazy-loading of custom elements, automatic reconnection to SSE servers, and unified prefixing for custom elements. The change also includes a design system integration, improved loading states, and a centered layout, all managed through the new \window.pe\ and \window.app\ APIs.

assets/js · high confidence

Introduce command handlers for game lifecycle and interactions

Added command and handler classes for managing game states and player interactions, including opening a new game with configurable board size, stone type, and timer; joining an existing game; making a move; assigning a chat channel; and handling game-ending actions like aborting, resigning, or timing out. These changes enable users to start, participate in, and conclude Connect Four games through specific application commands.

src/ConnectFour/Application/Game/Command · high confidence

Introduce common scheduler library for job scheduling

A new scheduler component has been added to the common library, providing a mechanism to schedule and execute jobs at specific times. The implementation includes a \PcntlScheduler\ that utilizes PHP's \pcntl\_alarm\ to trigger handlers when jobs are due, a \CollectJobsScheduler\ for collecting jobs, and a \TestScheduler\ for testing purposes. The core logic relies on a \Jobs\ collection to manage scheduled tasks, allowing for adding, removing, and filtering jobs based on their scheduled invocation time.

src/Common/Scheduler · high confidence

Introduce domain events and state machine for Connect Four games

The Connect Four domain now exposes a full set of domain events (e.g., GameWon, PlayerMoved, GameAborted) and a state machine (Open, Running, Won, Drawn, etc.) that tracks game progression. Users will see richer game state transitions and event-driven updates for moves, wins, draws, timeouts, and resignations.

src/ConnectFour/Domain/Game/Event · high confidence

Introduce domain exception classes for validation errors

The codebase now includes new exception classes in the \Gaming\\Common\\Domain\\Exception\ namespace to handle domain-level errors. \DomainException\ wraps a \Violations\ collection to represent violations of domain invariants, while \Violation\ and \ViolationParameter\ classes provide structured data about specific errors. Additionally, \Violations\ acts as an iterable container for these errors, and \ConcurrencyException\ has been introduced to handle concurrency issues, replacing the previous \PlayerNotOwnerException\.

src/Common/Domain/Exception · medium confidence

Introduce domain models for user and bot identity management

The identity domain now includes new domain models for managing user and bot accounts. Users can arrive and sign up with an email and username, while bots can be registered with a username. Both account types support domain events (UserArrived, UserSignedUp, BotRegistered) and enforce uniqueness constraints for emails, usernames, and account IDs. The Accounts repository interface has been updated to retrieve accounts by ID, and exception classes have been restructured to support the new identity model.

src/Identity/Domain · high confidence

Introduce game domain model with player and dealer abstractions

The game domain model is introduced with a new \Game\ aggregate that manages the lifecycle of a memory game, including opening, joining, leaving, and starting games. Players are tracked via a \PlayerPool\ that handles joining and leaving, while a \Dealer\ interface with \LazyDealer\ and \ShuffleDealer\ implementations manages card distribution. Game identities are generated as UUID v6, and domain events (e.g., \GameOpened\, \PlayerJoined\, \PlayerLeft\) are emitted to track state changes.

src/Memory/Domain/Model/Game · high confidence

Introduce generic sharding interface and implementations

Added a new generic Shards interface and two concrete implementations: Crc32ModShards for simple hash-based distribution and DoctrineMySqlSchemaShards for routing MySQL connections to specific schemas. This provides a reusable, abstracted sharding strategy that can be used across different contexts, such as the Connect Four game logic. The ShardingException class has been moved and renamed to reflect its new home in the Common/Sharding namespace.

src/Common/Sharding · high confidence

Introduce new HTTP controllers and home page template

The web interface now includes dedicated controllers for the home page and server time, alongside a new Twig template for the home view. This establishes the foundational HTTP endpoints and UI structure for the web interface, replacing previous abstractions with a more direct routing and rendering approach.

src/WebInterface/Presentation · medium confidence

Introduce new MessageBroker and Prometheus metrics middleware components

Added a new MessageBroker component providing a PSR-14 event-driven consumer and publisher interface with an AMQP/AmqpLib integration that supports sharded queues, message routing, and context-based acknowledgements. Additionally, introduced a Doctrine DBAL middleware stack (CollectMetricsConnection, CollectMetricsDriver, CollectMetricsMiddleware, and CollectMetricsStatement) to automatically track and expose SQL query durations as Prometheus histograms.

src/Common/MessageBroker · high confidence

Introduce new chat widget and service layer

A new chat widget has been added to the frontend, featuring a dedicated service for sending and retrieving messages, along with a custom element that renders chat bubbles with author usernames and timestamps. The implementation includes logic to handle message buffering, duplicate detection, and automatic retry on failure, providing users with a functional chat interface.

assets/js/Chat · high confidence

Introduce schema versioning and migration support for normalizers

The Normalizer component now supports automatic schema migrations. A new Normalizer interface defines the contract, with a JmsSerializerNormalizer implementation for JMS Serializer integration. A MigratingNormalizer wrapper applies versioned migrations during denormalization and tracks versions during normalization. A Migrations class manages the migration chain, and a NormalizerException replaces the previous GameNotFoundException. Test fixtures (TestNormalizer, TestMigration) are also added.

src/Common/Normalizer · high confidence

Introduce structured winning rule system for Connect Four

The Connect Four domain now uses a dedicated WinningRule system to detect and return winning sequences. A new WinningRules collection iterates over vertical, horizontal, and diagonal checks, returning the specific points that form a winning line. This replaces previous ad-hoc logic with a clear, extensible structure for identifying game-ending moves.

src/ConnectFour/Domain/Game/WinningRule · high confidence

Introduce unified channel abstraction for inter-process communication

A new \Gaming\\Common\\ForkPool\\Channel\ namespace has been added, introducing a \Channel\ interface and a \ChannelPair\ to standardize communication between parent and forked processes. The implementation includes \StreamChannel\ for socket-based messaging, a \Channels\ class for managing multiple channels with round-robin or consistent hashing strategies, and factory classes (\StreamChannelPairFactory\, \NullChannelPairFactory\) to create these channel pairs. This change provides a consistent API for sending and receiving messages, supporting synchronization and timeout handling across the fork pool.

src/Common/ForkPool/Channel · high confidence

Introduced domain events for chat interactions

Added new domain event classes, ChatInitiated and MessageWritten, which implement the DomainEvent interface. ChatInitiated captures the chat ID when a chat is created, while MessageWritten records details about a written message, including the chat ID, message ID, author ID, message content, and timestamp. These events enable tracking and handling of chat-related state changes within the application.

src/Chat/Application/Event · medium confidence

Introduced new domain events for game lifecycle and player actions

Added new domain event classes—GameClosed, GameOpened, GameStarted, PlayerJoined, and PlayerLeft—to the game domain model. These events capture key moments in the game's lifecycle and player interactions, implementing the DomainEvent interface and exposing relevant state (such as game ID, player IDs, and card counts) for downstream processing.

src/Memory/Domain/Model/Game/Event · high confidence

Introduced new query handlers and models for game retrieval

Added new query handlers and request objects to the application layer, including GameHandler, GamesByPlayerHandler, OpenGamesHandler, and RunningGamesHandler, each paired with their respective query classes (GameQuery, GamesByPlayerQuery, OpenGamesQuery, RunningGamesQuery). These handlers expose endpoints for retrieving a single game, listing games by player, listing open games, and counting running games. Additionally, the RunningGames model was moved from the code/ directory to the main src/ directory and updated with strict typing.

src/ConnectFour/Application/Game/Query · high confidence

New BusException class for message bus errors

A new BusException class has been added to the Common/Bus/Exception directory. This class extends the standard PHP Exception and provides a static factory method, missingHandler, which generates a descriptive error message when a message bus handler is not found for a given request class.

src/Common/Bus/Exception · high confidence

New Connect Four game creation and challenge flow

Users can now create new Connect Four games with specific configurations, including board size (7x6, 9x6, 11x8, 13x10), game variant (Standard, PopOut), timer settings (move-based or game-based), and player color selection. The new ChallengeController and OpenType form handle the game creation and challenge acceptance flow, while FragmentController exposes open games and statistics endpoints. Game interactions like joining, aborting, resigning, and making moves are handled via the GameController, and the PageController manages the lobby, game view, and history pages.

src/ConnectFour/Port/Adapter/Http · high confidence

New Redis-backed persistence adapters for game queries and open games

The repository layer now includes new persistence adapters for querying and caching game data. A Doctrine-based JSON repository (DoctrineJsonGameRepository) handles game persistence using the Doctrine DBAL connection. Additionally, several new Redis-backed stores have been introduced to optimize query performance: an in-memory cache store (InMemoryCacheGameStore), a Predis-based game store (PredisGameStore) with pending flush logic, and specialized stores for open games (PredisOpenGameStore) and running games (PredisRunningGameStore) that leverage Redis sorted sets and sets for efficient state tracking.

src/ConnectFour/Port/Adapter/Persistence/Repository · high confidence

New bus integrations for Doctrine, Symfony, and transactional handling

Added new integration classes for the command/query bus: DoctrineClearManagerBus to clear the Doctrine object manager after each request, DoctrineTransactionalBus to wrap requests in database transactions, SymfonyValidatorBus to validate requests using Symfony's Validator component, and GamingPlatformBusBundle to configure and wire these buses via Symfony DI.

src/Common/Bus/Integration · high confidence

New game query model and persistence interfaces

A new query model for the Connect Four game has been introduced, consisting of the Game value object, Move entity, and associated interfaces (GameFinder, GameStore). The Game class projects domain events (such as GameOpened, PlayerJoined, PlayerMoved, and various game-ending states) to maintain the current state, including player turns, remaining time, and winning sequences. This allows the application to efficiently retrieve and persist game data for read operations, separating the query side from the domain model.

src/ConnectFour/Application/Game/Query/Model/Game · high confidence

New integration components for structured validation error handling

Three new classes have been added to the common domain integration layer to standardize how validation violations are reported. The \FormViolationMapper\ maps domain violations to Symfony form errors, enabling consistent UI feedback. The \RespondWithViolationsAsJsonOnKernelExceptionListener\ converts \DomainException\s into structured JSON responses containing violation details and appropriate HTTP status codes. The \ReplyWithErrorResponseOnMessageFailedListener\ handles failed messages by replying with a standardized error response containing violation data. Together, these components provide a unified mechanism for translating internal validation exceptions into both HTTP and message-broker error responses.

src/Common/Domain/Integration · high confidence

New messaging adapters for Connect Four game logic

Added new message handlers and subscribers in the Connect Four messaging port to bridge domain events and RPC requests with the message broker and browser notifications. This includes publishing domain events to the message broker, handling RPC calls for game operations (open, join, move, query), and routing broker messages to browser notifications or internal commands.

src/ConnectFour/Port/Adapter/Messaging · high confidence

New projection adapters for game state queries

Added new projection classes (GameProjection, GamesByPlayerProjection, OpenGamesProjection, RunningGamesProjection, and TimerProjection) that implement the StoredEventSubscriber interface to process domain events and update query models. These adapters handle specific game states (open, running, timed out, etc.) and manage timeouts, enabling the system to efficiently query and filter games by their current status.

src/ConnectFour/Port/Adapter/Persistence/Projection · high confidence

New shared UI components and utilities for the frontend

The frontend now includes several new JavaScript modules in the Common directory to enhance user interaction and state management. A ConfirmationButton component provides a two-step confirmation flow for destructive actions. An EventSource module manages Server-Sent Events with automatic reconnection and debounced subscriptions. An EventSourceStatus component offers visual indicators for connection state. An HttpClient class standardizes JSON API calls. A NotificationList component handles temporary alert messages. A ServerTime utility synchrons client time with the server. A VolumeControl component allows users to adjust audio levels via a slider. These additions support a more interactive and responsive user experience.

assets/js/Common · high confidence

New shared layout templates for the gaming platform

The templates/layout directory now contains new shared layout templates: base.html.twig, center-tight.html.twig, condensed.html.twig, and a footer-links partial. These templates define the site's head section, navigation, and footer, providing a consistent structure for all pages. The condensed layout includes a header with game selection, user authentication status, and volume control, while the center-tight layout provides a centered content area with flash messages and footer links.

templates/layout · high confidence

Real-time chat notifications via browser push

Users now receive immediate browser notifications when new messages are sent in a chat. This is achieved by introducing a new subscriber that publishes domain events to a message broker, and a corresponding message handler that translates those broker events into browser push notifications, including the sender's actual username.

src/Chat/Infrastructure/Messaging · high confidence

Standardize development environment with .env configuration and project script

The application now uses a centralized .env file to define environment variables for all contexts (Chat, Connect Four, Identity, Web Interface) and shared settings, replacing the previous environment.env file. A new 'project' shell script provides a unified interface for development tasks including building the environment, running tests (unit, sniffer, analyzer, acceptance), managing assets, and handling Composer commands. The script also supports building and pushing production Docker images. Configuration files for code sniffer (phpcs.xml.dist) and static analysis (phpstan.neon.dist) are added to enforce coding standards and code quality.

(repo-wide) · high confidence

Removals

Removal of legacy Symfony-based infrastructure and configuration

The application's legacy Symfony infrastructure has been removed, including the \Makefile\ build script, the \bin/console\ entry point, and all YAML configuration files for service definitions, routing, and migrations. This eliminates the previous dependency on Symfony's dependency injection container and console components, indicating a shift away from the Symfony framework for the web interface layer.

code · high confidence

Behavioural changes

Add environment variable to run all database migrations on startup

The entrypoint script now checks for the APP\_CONNECT\_FOUR\_RUN\_MIGRATIONS or APP\_RUN\_MIGRATIONS environment variables. If set to '1', it iterates through the comma-separated list in APP\_CONNECT\_FOUR\_DOCTRINE\_DBAL\_SHARDS and runs database creation and migration for each shard, ensuring the database schema is up to date at startup.

bin/connect-four · medium confidence

Added console commands for game timeout handling and running game count publishing

Two new console commands have been introduced in the Connect Four module. The first, HandleTimeoutsCommand, manages game timeouts by delegating to a TimeoutCommand via the command bus, integrating with Prometheus metrics and a common timeout service. The second, PublishRunningGamesCountToNchanCommand, periodically queries the number of running games and publishes updates via a browser notifier when the count changes, enabling real-time lobby status updates.

src/ConnectFour/Port/Adapter/Console · medium confidence

Automatic database migrations on startup

The chat and identity services now automatically create their respective databases and run all pending migrations when the APP\_CHAT\_RUN\_MIGRATIONS, APP\_IDENTITY\_RUN\_MIGRATIONS, or APP\_RUN\_MIGRATIONS environment variables are set to 1.

bin/chat, bin/identity · high confidence

Centralized configuration and routing structure

The application's configuration has been reorganized into a unified \config/\ directory, consolidating environment-specific settings (\config.yml\, \config\_dev.yml\, \config\_prod.yml\) and routing definitions. This change introduces a structured service container setup for message broker connections, periodic heartbeat handling for Doctrine, and Prometheus metrics collection. Additionally, the development environment routing has been updated to use PHP-based routing files for the Web Profiler, and asset import maps are now explicitly defined for frontend dependencies.

config · high confidence

Customize form layout and error display for button groups

A new template file, templates/tabler\_form\_layout.html.twig, has been added to override default form rendering. This change allows form choices to be rendered as buttons by ignoring label attributes for expanded choices and ensures that required indicators are removed from individual choice labels. Additionally, form error messages are now displayed using a reusable alert component for root forms and as inline feedback for other forms.

templates · medium confidence

Customized default error pages for 404 and internal server errors

The application now displays custom-styled error pages for 404 (Page Not Found) and 500 (Internal Server Error) exceptions. These new templates provide a consistent user experience with centered layouts, specific error messages, and a 'Take me home' button, replacing the previous default error page styles.

templates/bundles · high confidence

Enforce stricter username and email validation rules

The system now applies stricter validation for user and bot accounts. Usernames must be 3-20 characters, use only letters, numbers, and underscores (no leading, trailing, or consecutive underscores), and cannot match reserved patterns or specific reserved words. Emails must be valid and not already in use. These changes ensure that new accounts have unique, properly formatted credentials.

src/Identity/Port/Adapter/Validation · high confidence

Introduce Doctrine-based persistence for user, bot, and account repositories

Users and bots can now be persisted and retrieved via new Doctrine repository implementations (DoctrineUserRepository, DoctrineBotRepository, DoctrineAccountRepository). This adds support for saving user and bot records, fetching users by ID or email, looking up bots by username, and loading accounts by ID, with specific exception handling for duplicate emails, usernames, and concurrency conflicts.

src/Identity/Port/Adapter/Persistence/Repository · high confidence

Introduce chat-specific exception classes for application errors

The application now includes a dedicated set of exception classes for the Chat module, including ChatException as the base, along with specific exceptions for scenarios such as an author not being allowed, a chat already existing, a chat not being found, empty messages, and duplicate messages. These classes extend the new ChatException, which was migrated and renamed from the previous PlayerHasInvalidStoneException, aligning error handling with the chat domain.

src/Chat/Application/Exception · high confidence

Introduce domain-specific exception classes for Connect Four game rules

Added a set of new exception classes in the Connect Four domain to handle specific game state violations, including ColumnAlreadyFilledException, GameFinishedException, GameNotFoundException, GameNotRunningException, GameRunningException, NoTimeoutException, OutOfSizeException, PlayerHasInvalidStoneException, PlayerNotOwnerException, PlayersNotUniqueException, SizeProductNotEvenException, SizeTooSmallException, UnexpectedPlayerException, and WinningSequenceLengthTooShortException. These exceptions extend the updated GameException base class, which now extends DomainException, and are used to enforce game rules such as column capacity, game status, player ownership, and board size constraints.

src/ConnectFour/Domain/Game/Exception · high confidence

Introduce typed model and store for querying player's games

A new query model for retrieving a player's games has been added, consisting of a typed \GamesByPlayer\ value object, a \State\ enum for filtering by game status (all, open, running, won, lost, drawn), and a \GamesByPlayerStore\ interface defining methods to add games of various states and search for them by player ID, state, and pagination. This enables the profile page to filter and display games based on their current state.

src/ConnectFour/Application/Game/Query/Model/GamesByPlayer · high confidence

Introduce username caching and in-process resolution

The system now supports resolving usernames by account IDs through two new integration classes: ApcuUsernames, which caches username lookups in APCu for improved performance, and InProcessUsernames, which resolves usernames via an in-process bus. The Usernames interface has been moved and refactored to define a byIds method that returns an array of usernames, replacing the previous WinningRule interface used in the Connect Four domain.

src/Common/Usernames · medium confidence

Introduced domain-specific exception classes for game state validation

Added five new exception classes—GameNotFoundException, GameNotOpenException, PlayerAlreadyJoinedException, PlayerNotAllowedToStartGameException, and PlayerNotJoinedException—each extending the refactored GameException base class. These exceptions encapsulate specific game state violations (e.g., player not joined, pool empty) using a structured Violation/Violations approach, replacing the previous generic InvalidNumberOfRequiredMatchesException which was renamed and moved to serve as the base GameException.

src/Memory/Domain/Model/Game/Exception · high confidence

Introduces game configuration and state management for Connect Four

Users can now configure game settings such as board size, winning rules, and time controls. The game logic has been refactored to use a state pattern, allowing for clearer transitions between game states like open, playing, and finished. Additionally, the system now supports assigning chat IDs to games and managing player turns with timers.

src/ConnectFour/Domain/Game · high confidence

Migrate to Symfony 7 and modernize bin scripts

The application has been upgraded to Symfony 7, which includes a new default behavior for the Dotenv component and replaces the deprecated symfony/debug package with symfony/error-handler. The bin/console entry point has been updated to use the new Kernel class and the Symfony/runtime component for runtime handling. Additionally, a new bin/restartOnChange script has been added to automatically restart the application on file changes during development.

bin · medium confidence

New Dockerfile and build scripts for PHP 8.5

The Docker build process has been updated to use PHP 8.5, with a new Dockerfile and associated shell scripts (composer-install.sh, entrypoint.sh, warmup.sh) that configure PHP-FPM and CLI environments for both development and production modes. The warmup script now explicitly handles cache warming, importmap installation, and asset compilation based on the environment, while the entrypoint script manages pre-start hooks and TCP server waits.

docker · high confidence

New security and UI composition infrastructure

The web interface now includes a custom Symfony security implementation, introducing a \Security\ class that automatically creates a guest user session via an \ArriveCommand\ when no user is present, and a \User\ entity implementing \UserInterface\ with role and credential management. A \UserProvider\ handles loading and refreshing user data from the identity system with a configurable cache interval. Additionally, the application now supports Server-Side Includes (SSI) for UI composition by rendering fragment exceptions as \\<pe-include\>\ tags, and notifies the browser about login events via a \Pe-Dispatch\ header to handle redirections gracefully.

src/WebInterface/Infrastructure · medium confidence

Redesigned game board layout and interactive states

The game board now uses CSS Grid for a responsive layout, with each field styled as a circle (aspect-ratio: 1) and a highlight animation to indicate the current move. A progress bar animation and loading states have been added to improve the user experience during transitions and loading. Additionally, scroll padding has been adjusted to account for sticky headers, ensuring content is not obscured.

assets/css · medium confidence

Refactor open game query model and store interface

The OpenGame model class was created to represent a game's state with typed properties (gameId, width, height, playerId). A new OpenGameStore interface was introduced to manage saving, removing, and listing open games. The existing OpenGames collection class was moved from the code/ directory to src/ and updated to use PHP 7.4+ typed properties instead of untyped ones.

src/ConnectFour/Application/Game/Query/Model/OpenGames · medium confidence

Refactored BrowserNotifier to support multiple channels and Nchan integration

The BrowserNotifier interface was moved from the WebInterface layer to the Common layer and updated to accept an array of channels instead of a single channel string, allowing notifications to be broadcast to multiple destinations simultaneously. A new Nchan-based implementation was added to handle publishing via the Nchan server, utilizing a combined channel ID for message routing.

src/Common/BrowserNotifier · medium confidence

Refactored EventStore with new DomainEvent and subscriber abstractions

The EventStore component has been refactored to decouple domain logic from the event store implementation. A new \DomainEvent\ class now carries headers and versioning, replacing the previous \DomainEvent\ interface. The \EventStore\ interface now accepts \DomainEvent\ objects directly for appending, while a \PollableEventStore\ interface handles polling for subscribers. Subscribers are now split into \DomainEventSubscriber\ and \StoredEventSubscriber\ (with a \commit\ method), enabling a cleaner separation between domain and stored event handling. A \CleanableEventStore\ interface and \CleanUpEventStore\ listener allow for safe cleanup of committed events. The \InMemoryEventStore\ provides a simple in-memory implementation of the new \EventStore\ interface.

src/Common/EventStore · high confidence

Refactored application kernel and updated namespace

The application's entry point has been renamed from AppKernel to Kernel and moved from the code/app directory to src. The PHP namespace has been updated from Gambling to Gaming, and the code has been modernized to use PSR-12 standards, including strict typing and return type declarations. Additionally, several new bundles have been registered, including MareinLockDoctrineMigrationsBundle, MareinStandardHeadersCsrfBundle, MonologBundle, SecurityBundle, and GamingPlatformBusBundle, while removing the custom cache and log directory methods.

src · medium confidence

Refactored chat database schema and migrated to PSR-12 standards

The chat infrastructure migrations have been reorganized and updated to align with modern PHP standards. The 'chat' table migration now uses the 'uuid' column type instead of 'string', and the 'ownerId' column has been removed. The 'message' table migration has been updated to use 'uuid' types for 'chatId' and 'authorId', and includes new columns for 'writtenAt' and 'idempotencyKey'. Additionally, the migration files have been moved from 'code/src/Chat/Migration' to 'src/Chat/Infrastructure/Migration', and the namespace has been changed from 'Gambling\\' to 'Gaming\\'.

src/Chat/Infrastructure/Migration · high confidence

Refactored exception hierarchy for EventStore module

The exception classes in the EventStore module have been restructured to use a new base class, EventStoreException, replacing the previous generic or bus-specific exception bases. Specific exceptions such as DuplicateVersionInStreamException, FailedRetrieveMostRecentPublishedStoredEventIdException, and FailedTrackMostRecentPublishedStoredEventIdException now extend this new common base, and the namespace has been updated to reflect the EventStore domain.

src/Common/EventStore/Exception · medium confidence

Refined Connect Four board domain model with typed properties and enums

The Connect Four board domain has been refactored to use modern PHP features: the Stone type is now an enum with a random selection method, and classes like Board, Field, Point, and Size have been migrated to typed properties and constructor promotion. This improves type safety and code clarity for game state representation.

src/ConnectFour/Domain/Game/Board · high confidence

Removal of legacy container definitions and environment configuration

The container directory has been restructured by removing all existing Dockerfile definitions and configuration files. Specifically, the build and runtime containers for Composer, frontend building, MySQL, Nginx, PHP (both FPM and CLI), and RabbitMQ have been deleted, along with the shared environment variables file that previously defined database, Redis, RabbitMQ, and Nchan connection strings for various application contexts.

container · high confidence

Updated JMS serialization configuration and added migration for stone representation

The JMS serializer configuration for the JMS persistence adapter has been updated to include explicit mapping for domain events, timers, game states, and winning rules. Additionally, new serialization handlers have been added for Field, GameId, and Stone types to control their JSON representation. A migration strategy has also been introduced to convert the previous nested stone object structure into a scalar value during deserialization, ensuring backward compatibility with existing stored data.

src/ConnectFour/Port/Adapter/Persistence/Jms · high confidence

Updated database migration to use UUID v6 and modernize schema

The persistence migration for the 'game' table has been updated to use the 'uuid' column type instead of a fixed-length string, and the primary key index on 'id' and 'version' has been removed. Additionally, the migration class now extends the modern Doctrine Migrations base class and includes strict typing and namespace updates.

src/ConnectFour/Port/Adapter/Persistence/Migration · medium confidence

Test coverage

Add acceptance tests for game interactions; Added DomainAssert helper for testing domain exceptions; Added integration tests for the Doctrine periodic heartbeat middleware; Added test fixtures for the command bus; Added test support classes and helpers for acceptance and unit testing; Added unit tests for ChatId and ChatService; Added unit tests for Connect Four board domain classes; Added unit tests for Connect Four game domain; Added unit tests for Connect Four winning rule logic; Added unit tests for FormViolationMapper; Added unit tests for Game domain model; Added unit tests for Identity domain models; Added unit tests for MigratingNormalizer; Added unit tests for PcntlScheduler; Added unit tests for SymfonyValidatorBus; Added unit tests for game dealer implementations; Added unit tests for the Common Bus components; Added unit tests for the ForkPool Channel synchronization and selection strategies; Added unit tests for the Game query model.

Dependencies

Upgrade to PHP 8.5 and Symfony 7

The project's dependencies have been updated to require PHP 8.5 and upgrade the Symfony framework to version 7. This includes updating core packages such as \symfony/framework-bundle\, \symfony/security-bundle\, and \symfony/validator\ to their 7.0+ versions, alongside other library updates like \doctrine/dbal\ to 4.0 and \phpunit\ to 12.5.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 58 → 52 (-5.7)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 65 → 68 (+2.6)
  • Architecture 99 → 92 (-6.5)
  • Maturity 63 → 55 (-8.0)
  • Readiness 46 → 51 (+4.2)
  • Security 63 → 67 (+3.5)
  • Domain Modelling 91 → 88 (-3.9)
  • Accessibility 45 (new)

Resolved (52)

  • Change coupling: AbortButton.js ↔ Game.js (assets/js/ConnectFour/AbortButton.js)
  • Change coupling: ChatService.js ↔ GameService.js (assets/js/Chat/ChatService.js)
  • Change coupling: Game.js ↔ ResignButton.js (assets/js/ConnectFour/Model/Game.js)
  • Change coupling: Game.js ↔ RunningGames.js (assets/js/ConnectFour/Game.js)
  • Change coupling: GameList.js ↔ RunningGames.js (assets/js/ConnectFour/GameList.js)
  • Change coupling: Widget.js ↔ RunningGames.js (assets/js/Chat/Widget.js)
  • Change coupling: app.js ↔ importmap.php (assets/js/app.js)
  • Coverage not included — suite not readable by the collector
  • Critical CVE: [GHSA redacted] (composer.lock)
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • Duplicated block (13 lines × 2) (src/Common/EventStore/Integration/Symfony/FollowEventStoreCommand.php)
  • Duplicated block (9 lines × 2) (src/Identity/Port/Adapter/Http/SignupController.php)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • Low CVE: [GHSA redacted] (composer.lock)
  • Low CVE: [GHSA redacted] (composer.lock)
  • Medium CVE: [GHSA redacted] (composer.lock)
  • …and 32 more

New (116)

  • Boundary-crossing change coupling: ChatController.php ↔ GameController.php (src/Chat/Presentation/Http/ChatController.php)
  • Critical CVE: [GHSA redacted] (composer.lock)
  • Documentation: no installation or build instructions (README.md)
  • Documentation: no usage examples (README.md)
  • Dormant codebase
  • Duplicated block (12 lines × 2) (src/Memory/Domain/Model/Game/Event/PlayerJoined.php)
  • Duplicated block (14–16 lines × 2) (src/Common/EventStore/Integration/Symfony/FollowEventStoreCommand.php)
  • Duplicated block (25 lines × 5) (src/ConnectFour/Domain/Game/State/Aborted.php)
  • Duplicated block (9 lines × 2) (src/Identity/Port/Adapter/Http/SignupController.php)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • High CVE: [GHSA redacted] (composer.lock)
  • High IaC: WD-COMPOSE-0001 (deploy/single-server/docker-compose.yml)
  • High IaC: WD-COMPOSE-0001 (deploy/single-server/docker-compose.yml)
  • High IaC: WD-COMPOSE-0001 (docker-compose.ci.yml)
  • High IaC: WD-COMPOSE-0001 (docker-compose.yml)
  • High IaC: WD-COMPOSE-0001 (docker-compose.yml)
  • …and 96 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

marein/php-gaming-website was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit c2ea522ae03517ce46cd8024ad030d76e6ecb9b2 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-fa71c66cabd8.