Skip to content

Refactor registration command CQRS flow#282

Open
dmytrocraft wants to merge 61 commits into
mainfrom
codex/issue-217-register-user-cqrs
Open

Refactor registration command CQRS flow#282
dmytrocraft wants to merge 61 commits into
mainfrom
codex/issue-217-register-user-cqrs

Conversation

@dmytrocraft

@dmytrocraft dmytrocraft commented May 10, 2026

Copy link
Copy Markdown
Contributor

Description

Refactors user registration so RegisterUserCommand is a write-side request only. Existing-user lookups and created-user response resolution now live in the REST processor and GraphQL resolver through a dedicated FindUserByEmailQueryHandler, while RegisterUserCommandHandler only creates users and publishes registration events.

Also removes RegisterUserCommandResponse, updates affected unit tests, documents the CQRS command/response boundary, and adds issue #217 planning artifacts under specs/issue-217-register-user-cqrs/.

Related Issue

Closes #217

Motivation and Context

The registration command previously behaved as both a command and response container, which blurred CQRS responsibilities. This keeps registration API behavior stable while separating write-side command handling from read-side response lookup.

How Has This Been Tested?

Local full CI passed with custom ports to avoid workspace conflicts:

  • make ci
  • Focused post-cleanup PHPUnit run: ./vendor/bin/phpunit tests/Unit/User/Application/Resolver/RegisterUserMutationResolverTest.php tests/Unit/User/Application/Processor/RegisterUserProcessorTest.php tests/Unit/User/Application/Query/FindUserByEmailQueryHandlerTest.php tests/Unit/User/Application/Command/SignUpCommandTest.php tests/Unit/User/Application/CommandHandler/SignUpCommandHandlerTest.php

Full local CI included unit, integration, Behat, Psalm, Psalm taint/security, Deptrac, PHP Insights, OpenAPI diff/validation, Schemathesis, and Infection. Infection result: 4559/4559 mutants killed, MSI 100%.

Performance changes: none expected. This change adds one explicit post-dispatch read on the new-user registration path to resolve the created user outside the command handler; existing-user registration short-circuits before dispatch as before.

Screenshots (if appropriate):

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • I have performed a self-review of my code.
  • I have commented my code, particularly in hard-to-understand areas.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING.md document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • You have only one commit (if not, squash them into one commit).
  • Structurizr documentation has been updated to reflect any architectural changes.

Summary by cubic

Refactors registration CQRS so the handler creates users and returns RegisterUserCommandResponse.user while keeping REST/GraphQL behavior unchanged. Enforces case-insensitive email uniqueness via stored normalizedEmail with a partial unique index; adds an operational backfill runbook and BMAD manual evidence; documents 409 conflicts for ambiguous OAuth linking; addresses #217.

  • Refactors

    • Made RegisterUserCommand immutable; added RegisterUserCommandDispatcher, FindUserByEmailQueryHandler, EmailNormalizer, and UserPasswordHashFactory.
    • Enforced unique partial index on normalizedEmail; repositories/cache normalize emails; added backfill command with dry-run/report and report writer; included rollout runbook and BMAD manual evidence.
    • OAuth: return 409 for ambiguous/duplicate email linking; added SocialIdentityLinker; OpenAPI documents the 409 problem response.
    • Batch registration uses DTO inputs and indexed email lookup with a narrow legacy fallback.
  • Bug Fixes

    • Unified duplicate-email checks across registration, sign-in, password reset, 2FA, and GraphQL with translated errors.
    • Cache avoids negative-miss writes for email lookups; Docker supports MONGODB_IMAGE override.

Written for commit 951333c. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • More reliable duplicate-email detection and safer failure handling during registration; caching negative-miss behavior improved.
  • Refactor

    • Registration split into read vs write responsibilities with an orchestration step to enforce duplicate checks while preserving API behavior.
  • New Features

    • System-wide email normalization (trim + multibyte-safe lowercase) and translated duplicate-email validation message added.
  • Documentation

    • Architecture, PRD, epics, readiness, research and run-summary docs updated.
  • Tests

    • Expanded coverage for registration, email normalization, caching and duplicate-email scenarios.

Review Change Stack

BMAD Planning Evidence

@dmytrocraft dmytrocraft requested a review from Kravalg May 10, 2026 05:56
@qodo-code-review

Copy link
Copy Markdown
ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one.

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors register-user into CQRS: commands become immutable input-only; command response DTO removed; EmailNormalizer and FindUserByEmail query handler added; RegisterUserOrchestrator coordinates pre-check/dispatch/post-check; processor/resolver delegate to orchestrator; repositories, cache, validator, and tests updated.

Changes

Register User CQRS Refactor

Layer / File(s) Summary
Specification and planning
specs/issue-217-register-user-cqrs/*, docs/design-and-architecture.md
Adds PRD, architecture, epics, research, product brief/distillate, run-summary, implementation-readiness, and clarifies CQRS command semantics.
Command immutability & DTO removal
src/User/Application/Command/RegisterUserCommand.php, src/User/Application/DTO/RegisterUserCommandResponse.php, tests/Unit/User/Application/Command/*
RegisterUserCommand is readonly containing only inputs; RegisterUserCommandResponse removed; tests updated/added for command constructor and response-focused tests removed.
Email normalizer & query handler
src/User/Application/Service/EmailNormalizer.php, src/User/Application/Query/*, config/services.yaml
Adds EmailNormalizer; new FindUserByEmailQueryHandlerInterface + implementation that normalizes email, prefers exact match, falls back to case-insensitive collection, and throws on ambiguous results; service alias registered.
Orchestrator and delegation
src/User/Application/Registration/RegisterUserOrchestrator.php, src/User/Application/Processor/RegisterUserProcessor.php, src/User/Application/Resolver/RegisterUserMutationResolver.php
Introduces RegisterUserOrchestrator coordinating pre-dispatch duplicate guard, command dispatch, and post-dispatch reload; Processor and GraphQL Resolver delegate to orchestrator and return UserInterface.
Command handler write-only
src/User/Application/CommandHandler/RegisterUserCommandHandler.php, tests/Unit/.../RegisterUserCommandHandlerTest.php
Handler now normalizes email (EmailNormalizer), reconstructs normalized command, returns void, transforms to User, hashes password, saves, and publishes UserRegisteredEvent; tests cover success and save-failure scenarios.
Repository & persistence
src/User/Domain/Repository/UserRepositoryInterface.php, src/User/Infrastructure/Repository/MongoDBUserRepository.php, src/User/Infrastructure/Repository/UserRepositoryDecorator.php
Adds findByEmailCaseInsensitive to repo API; MongoDB repo normalizes/extends email candidates, exposes case-insensitive lookup, detaches failed documents on save error, and maps duplicate-key email persistence failures to DuplicateEmailException (new domain exception). Decorator implements the fast-path exact-match then delegate behavior.
Cached repo & cache behavior
src/User/Infrastructure/Repository/CachedUserRepository.php, tests/Unit/.../CachedUserRepositoryFindByEmailCacheStoreTest.php
CachedUserRepository tracks cache-loader/fallback usage, avoids storing negative-cache on miss, deletes stale negative cache entries before fallback; tests updated for skipped negative-cache write and stale-entry fallback, and for case-insensitive normalized cache hits.
Validation & fixtures
src/Shared/Application/Validator/EmailUniquenessValidator.php, config/validator/validation.yaml, tests/Unit/.../InMemoryUserRepository.php
EmailUniquenessValidator now uses EmailNormalizer, checks exact normalized candidates then falls back to case-insensitive repository search; UniqueEmail constraint removed from CreateUserMutationInput; in-memory fixtures and validator tests updated for normalized lookup behavior.
Batch registration changes
src/User/Application/Factory/BatchUserRegistrationFactory.php, src/User/Application/CommandHandler/RegisterUserBatchCommandHandler.php
Batch APIs accept plain array $users payloads, validate entries, normalize email keys, detect duplicate normalized keys and throw DuplicateEmailException, and pass arrays to factories; tests adjusted.
Tests & test-support
tests/Unit/**, tests/Unit/.../Support/*
Extensive unit test additions and refactors: orchestrator, command handler, query handler, validator, repository, cache, batch processing, EmailNormalizer, recovery-code factory tests, and new test support helpers/base classes.
Config & architecture tooling
config/services.yaml, deptrac.yaml
Service alias for FindUserByEmailQueryHandlerInterface added; deptrac updated to recognize Registration-suffixed classes and a new MongoDB layer.
Feature tests
features/*
Behat GraphQL scenarios updated: duplicate-email error text expectation adjusted, scenario inputs made concrete for negative-validation cases.

Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels
refactor, backend, testing

Suggested reviewers

  • pixelTM
  • Derane

Sequence Diagram(s)

sequenceDiagram
  participant API as API (Processor/Resolver)
  participant Orch as RegisterUserOrchestrator
  participant QH as FindUserByEmailQueryHandler
  participant Repo as UserRepository / MongoDB
  participant Bus as CommandBus
  participant CH as RegisterUserCommandHandler

  API->>Orch: register(email, initials, password)
  Orch->>QH: find(email)
  QH->>Repo: findByEmail(normalized)
  Repo-->>QH: ?User
  alt user exists
    QH-->>Orch: User -> Orch throws DuplicateEmailException
    Orch-->>API: Duplicate error
  else not found
    Orch->>Bus: dispatch(RegisterUserCommand)
    Bus->>CH: invoke(command)
    CH->>Repo: save(user)
    CH->>Bus: publish(UserRegisteredEvent)
    CH-->>Bus: void
    Bus-->>Orch: dispatch complete
    Orch->>QH: find(email)  -- post-dispatch reload
    QH->>Repo: findByEmail(normalized)
    Repo-->>QH: User
    QH-->>Orch: User
    Orch-->>API: User
  end
Loading

Poem

"A rabbit wrote a patch with haste,
Trimmed and lowercased each email's waste.
Orchestrator hops, queries then sends,
No side-effects now — the flow ascends.
🥕✨"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/issue-217-register-user-cqrs

@qltysh

qltysh Bot commented May 10, 2026

Copy link
Copy Markdown

3 new issues

Tool Category Rule Count
qlty Structure Function with many parameters (count = 7): __construct 2
qlty Duplication Found 14 lines of similar code in 4 locations (mass = 114) 1

Comment thread specs/issue-217-register-user-cqrs/architecture.md
Comment thread specs/issue-217-register-user-cqrs/epics.md
Comment thread specs/issue-217-register-user-cqrs/implementation-readiness.md
Comment thread specs/issue-217-register-user-cqrs/prd.md
Comment thread specs/issue-217-register-user-cqrs/product-brief-distillate.md
Comment thread specs/issue-217-register-user-cqrs/product-brief.md
Comment thread specs/issue-217-register-user-cqrs/research.md
Comment thread specs/issue-217-register-user-cqrs/run-summary.md
Comment thread tests/Unit/User/Application/Processor/RegisterUserProcessorTest.php Outdated
Comment thread tests/Unit/User/Application/Resolver/RegisterUserMutationResolverTest.php Outdated
Signed-off-by: Vadym <kostiukdsfv@gmail.com>
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes May 10, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 8 files (changes from recent commits).

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 24 files

Confidence score: 3/5

  • There is a concrete validation-order risk in src/User/Application/Resolver/RegisterUserMutationResolver.php: reading email from $args before validation can trigger failures on malformed input before the validator runs.
  • Because this issue is severity 6/10 with high confidence (9/10) and affects request handling behavior, it introduces moderate user-facing regression risk until fixed.
  • This should be straightforward to address by validating the input payload first and only then accessing required keys like email.
  • Pay close attention to src/User/Application/Resolver/RegisterUserMutationResolver.php - ensure validation happens before any required argument access to avoid premature runtime errors.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/User/Application/Resolver/RegisterUserMutationResolver.php">

<violation number="1" location="src/User/Application/Resolver/RegisterUserMutationResolver.php:36">
P2: `email` is read from `$args` before input validation, so malformed input can fail before the validator handles it. Validate first, then access required keys.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant Client as REST/GraphQL Client
    participant API as API Platform
    participant Processor as RegisterUserProcessor
    participant Resolver as RegisterUserMutationResolver
    participant QueryHandler as FindUserByEmailQueryHandler
    participant CmdBus as CommandBus
    participant CmdHandler as RegisterUserCommandHandler
    participant Repo as UserRepository
    participant EventBus as EventBus

    Note over Client,EventBus: User Registration Flow (CQRS Refactored)

    alt Existing User (email already registered)
        Client->>API: POST /users (REST) or mutation (GraphQL)
        alt REST path
            API->>Processor: process(data)
            Processor->>QueryHandler: find(email)
            QueryHandler->>Repo: findByEmail(email)
            Repo-->>QueryHandler: Existing User
            QueryHandler-->>Processor: Existing User
            Processor-->>API: Return existing User
        else GraphQL path
            API->>Resolver: __invoke(null, context)
            Resolver->>QueryHandler: find(email)
            QueryHandler->>Repo: findByEmail(email)
            Repo-->>QueryHandler: Existing User
            QueryHandler-->>Resolvers: Existing User
            Resolver-->>API: Return existing User
        end
        API-->>Client: 200 OK + existing User

    else New User (email not found)
        Client->>API: POST /users (REST) or mutation (GraphQL)
        alt REST path
            API->>Processor: process(data)
            Processor->>QueryHandler: find(email)
            QueryHandler->>Repo: findByEmail(email)
            Repo-->>QueryHandler: null
            QueryHandler-->>Processor: null
            Processor->>CmdBus: dispatch(RegisterUserCommand)
            CmdBus->>CmdHandler: __invoke(command)
            CmdHandler->>Repo: save(user)
            CmdHandler->>EventBus: publish(UserRegisteredEvent)
            Processor->>QueryHandler: find(email)
            QueryHandler->>Repo: findByEmail(email)
            Repo-->>QueryHandler: New User
            alt User found
                QueryHandler-->>Processor: New User
                Processor-->>API: Return new User
            else User not found
                QueryHandler-->>Processor: null
                Processor-->>API: Throw UserNotFoundException
            end
        else GraphQL path
            API->>Resolver: __invoke(null, context)
            Resolver->>QueryHandler: find(email)
            QueryHandler->>Repo: findByEmail(email)
            Repo-->>QueryHandler: null
            QueryHandler-->>Resolver: null
            Resolver->>CmdBus: dispatch(RegisterUserCommand)
            CmdBus->>CmdHandler: __invoke(command)
            CmdHandler->>Repo: save(user)
            CmdHandler->>EventBus: publish(UserRegisteredEvent)
            Resolver->>QueryHandler: find(email)
            QueryHandler->>Repo: findByEmail(email)
            Repo-->>QueryHandler: New User
            alt User found
                QueryHandler-->>Resolver: New User
                Resolver-->>API: Return new User
            else User not found
                QueryHandler-->>Resolver: null
                Resolver-->>API: Throw UserNotFoundException
            end
        end
        API-->>Client: 200 OK + new User
    end

    Note over CmdHandler: Write-side only - no response mutation, no existing-user check
    Note over QueryHandler,Repo: Read-side query for pre-check and post-dispatch resolution
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread src/User/Application/Resolver/RegisterUserMutationResolver.php Outdated
@codecov

codecov Bot commented May 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (e5eb83e) to head (951333c).

Additional details and impacted files
@@              Coverage Diff              @@
##                main      #282     +/-   ##
=============================================
  Coverage     100.00%   100.00%             
- Complexity         0      2924   +2924     
=============================================
  Files            551       562     +11     
  Lines           9541      9987    +446     
=============================================
+ Hits            9541      9987    +446     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
specs/issue-217-register-user-cqrs/architecture.md (1)

47-57: 💤 Low value

Consider documenting post-dispatch query failure handling.

The orchestration flow correctly describes the pre-query, dispatch, and post-query pattern. However, step 4 (line 54) states "Query by email again and return the persisted user" without explicitly addressing what happens if the post-dispatch query returns null, which could occur if persistence failed or in race conditions.

While the AI summary indicates the implementation throws UserNotFoundException in this case, explicitly documenting this error path would make the architecture more complete and help future implementers understand the expected behavior.

📝 Suggested addition
 1. Query by email.
 2. Return existing user when found.
 3. Dispatch the command when missing.
-4. Query by email again and return the persisted user.
+4. Query by email again and return the persisted user (throw UserNotFoundException if not found).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/issue-217-register-user-cqrs/architecture.md` around lines 47 - 57, Add
explicit documentation for the post-dispatch-query failure case: in the
orchestration description for RegisterUserProcessor and
RegisterUserMutationResolver, state that after dispatching the register command
a second query-by-email is performed and if it returns null the implementation
should throw UserNotFoundException (or a clearly named domain error) to signal
persistence/runtime failure; include this failure path and the expected
exception in the architecture text so implementers know to handle/log and
surface this error from the resolver.
specs/issue-217-register-user-cqrs/research.md (1)

27-27: 💤 Low value

Remove unrelated repository observation.

The note about .github/copilot-instructions.md not being present appears unrelated to the CQRS refactor research and adds no value to understanding the current registration flow or the planned changes.

🧹 Suggested removal
 - The repository already exposes `findByEmail(string $email): ?UserInterface`.
-- `.github/copilot-instructions.md` is not present in this branch.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/issue-217-register-user-cqrs/research.md` at line 27, Remove the
unrelated repository observation mentioning ".github/copilot-instructions.md"
from the research note: delete the line "- `.github/copilot-instructions.md` is
not present in this branch." in specs/issue-217-register-user-cqrs/research.md
so the document only contains content relevant to the CQRS refactor and
registration flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@specs/issue-217-register-user-cqrs/research.md`:
- Line 48: There is a naming mismatch: the test file
SignUpCommandHandlerTest.php uses "SignUp" while the codebase/PR uses
RegisterUserCommand and RegisterUserCommandHandler; decide whether these are
distinct commands or the same and then rename or update accordingly—if they are
the same command, rename SignUpCommandHandlerTest.php to
RegisterUserCommandHandlerTest (and update any class/test names inside from
SignUp* to RegisterUser*), or if they are distinct, update the PR/docs to
reference SignUpCommand/SignUpCommandHandler where appropriate and ensure the
test targets the correct class (SignUpCommandHandlerTest -> tests the
SignUpCommandHandler class). Ensure all references to SignUpCommand,
SignUpCommandHandler, and SignUpCommandHandlerTest are consistently changed to
RegisterUserCommand, RegisterUserCommandHandler, and
RegisterUserCommandHandlerTest (or vice versa) so imports, assertions, and test
bootstrapping match the chosen terminology.

---

Nitpick comments:
In `@specs/issue-217-register-user-cqrs/architecture.md`:
- Around line 47-57: Add explicit documentation for the post-dispatch-query
failure case: in the orchestration description for RegisterUserProcessor and
RegisterUserMutationResolver, state that after dispatching the register command
a second query-by-email is performed and if it returns null the implementation
should throw UserNotFoundException (or a clearly named domain error) to signal
persistence/runtime failure; include this failure path and the expected
exception in the architecture text so implementers know to handle/log and
surface this error from the resolver.

In `@specs/issue-217-register-user-cqrs/research.md`:
- Line 27: Remove the unrelated repository observation mentioning
".github/copilot-instructions.md" from the research note: delete the line "-
`.github/copilot-instructions.md` is not present in this branch." in
specs/issue-217-register-user-cqrs/research.md so the document only contains
content relevant to the CQRS refactor and registration flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a8c0b6ed-0b8a-49d5-9c63-42065991a3be

📥 Commits

Reviewing files that changed from the base of the PR and between 202ec50 and 94fe891.

📒 Files selected for processing (24)
  • config/packages/test/cache.yaml
  • docs/design-and-architecture.md
  • specs/issue-217-register-user-cqrs/architecture.md
  • specs/issue-217-register-user-cqrs/epics.md
  • specs/issue-217-register-user-cqrs/implementation-readiness.md
  • specs/issue-217-register-user-cqrs/prd.md
  • specs/issue-217-register-user-cqrs/product-brief-distillate.md
  • specs/issue-217-register-user-cqrs/product-brief.md
  • specs/issue-217-register-user-cqrs/research.md
  • specs/issue-217-register-user-cqrs/run-summary.md
  • src/User/Application/Command/RegisterUserCommand.php
  • src/User/Application/CommandHandler/RegisterUserCommandHandler.php
  • src/User/Application/DTO/RegisterUserCommandResponse.php
  • src/User/Application/Processor/RegisterUserProcessor.php
  • src/User/Application/Query/FindUserByEmailQueryHandler.php
  • src/User/Application/Query/FindUserByEmailQueryHandlerInterface.php
  • src/User/Application/Resolver/RegisterUserMutationResolver.php
  • tests/Unit/User/Application/Command/RegisterUserBatchCommandResponseTest.php
  • tests/Unit/User/Application/Command/SignUpCommandResponseTest.php
  • tests/Unit/User/Application/Command/SignUpCommandTest.php
  • tests/Unit/User/Application/CommandHandler/SignUpCommandHandlerTest.php
  • tests/Unit/User/Application/Processor/RegisterUserProcessorTest.php
  • tests/Unit/User/Application/Query/FindUserByEmailQueryHandlerTest.php
  • tests/Unit/User/Application/Resolver/RegisterUserMutationResolverTest.php
💤 Files with no reviewable changes (4)
  • src/User/Application/CommandHandler/RegisterUserCommandHandler.php
  • tests/Unit/User/Application/Command/SignUpCommandResponseTest.php
  • tests/Unit/User/Application/Command/SignUpCommandTest.php
  • src/User/Application/DTO/RegisterUserCommandResponse.php

Comment thread specs/issue-217-register-user-cqrs/research.md Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 10, 2026
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes May 10, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 10 files (changes from recent commits).

Comment thread tests/Unit/User/Application/Processor/RegisterUserProcessorTest.php Outdated
Comment thread tests/Unit/User/Application/Resolver/RegisterUserMutationResolverTest.php Outdated
cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes May 10, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 2 files (changes from recent commits).

cubic-dev-ai[bot]
cubic-dev-ai Bot previously approved these changes May 10, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 3 files (changes from recent commits).

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 10, 2026
@dmytrocraft dmytrocraft requested review from Derane and pixelTM May 10, 2026 22:00
@dmytrocraft

Copy link
Copy Markdown
Contributor Author

Ready for human review. Current state: all CI checks are green, the branch is mergeable, and GitHub review threads show 0 unresolved. Human approval is the remaining requested step.

…ter-user-cqrs

# Conflicts:
#	config/packages/test/cache.yaml
@Kravalg

Kravalg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Code Review: PASS

Review Output
STATUS: PASS
0 issues.```
</details>

<details>
<summary>Verification Output</summary>

```text

Running on PHP 8.4.5, Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac.

JIT acceleration: OFF
You can enable JIT acceleration (experimental) with --force-jit.

Target PHP version: 8.4 (inferred from composer.json) Enabled extensions: dom, mongodb, simplexml.


Scanning files...


1 / 236...
10 / 236...
20 / 236...
30 / 236...
40 / 236...
50 / 236...
60 / 236...
70 / 236...
80 / 236...
90 / 236...
100 / 236...
110 / 236...
120 / 236...
130 / 236...
140 / 236...
150 / 236...
160 / 236...
170 / 236...
180 / 236...
190 / 236...
200 / 236...
210 / 236...
220 / 236...
230 / 236...
236 / 236...
240 / 301...
250 / 301...
260 / 301...
270 / 301...
280 / 301...
290 / 301...
300 / 301...
301 / 301...
310 / 633...
320 / 633...
330 / 633...
340 / 633...
350 / 633...
360 / 633...
370 / 633...
380 / 633...
390 / 633...
400 / 633...
410 / 633...
420 / 633...
430 / 633...
440 / 633...
450 / 633...
460 / 633...
470 / 633...
480 / 633...
490 / 633...
500 / 633...
510 / 633...
520 / 633...
530 / 633...
540 / 633...
550 / 633...
560 / 633...
570 / 633...
580 / 633...
590 / 633...
600 / 633...
610 / 633...
620 / 633...
630 / 633...
633 / 633...
640 / 805...
650 / 805...
660 / 805...
670 / 805...
680 / 805...
690 / 805...
700 / 805...
710 / 805...
720 / 805...
730 / 805...
740 / 805...
750 / 805...
760 / 805...
770 / 805...
780 / 805...
790 / 805...
800 / 805...
805 / 805...
810 / 872...
820 / 872...
830 / 872...
840 / 872...
850 / 872...
860 / 872...
870 / 872...
872 / 872...
880 / 902...
890 / 902...
900 / 902...
902 / 902...
910 / 920...
920 / 920...
930 / 953...
940 / 953...
950 / 953...
953 / 953...
956 / 956...
958 / 958...
960 / 2422...
970 / 2422...
980 / 2422...
990 / 2422...
1000 / 2422...
1010 / 2422...
1020 / 2422...
1030 / 2422...
1040 / 2422...
1050 / 2422...
1060 / 2422...
1070 / 2422...
1080 / 2422...
1090 / 2422...
1100 / 2422...
1110 / 2422...
1120 / 2422...
1130 / 2422...
1140 / 2422...
1150 / 2422...
1160 / 2422...
1170 / 2422...
1180 / 2422...
1190 / 2422...
1200 / 2422...
1210 / 2422...
1220 / 2422...
1230 / 2422...
1240 / 2422...
1250 / 2422...
1260 / 2422...
1270 / 2422...
1280 / 2422...
1290 / 2422...
1300 / 2422...
1310 / 2422...
1320 / 2422...
1330 / 2422...
1340 / 2422...
1350 / 2422...
1360 / 2422...
1370 / 2422...
1380 / 2422...
1390 / 2422...
1400 / 2422...
1410 / 2422...
1420 / 2422...
1430 / 2422...
1440 / 2422...
1450 / 2422...
1460 / 2422...
1470 / 2422...
1480 / 2422...
1490 / 2422...
1500 / 2422...
1510 / 2422...
1520 / 2422...
1530 / 2422...
1540 / 2422...
1550 / 2422...
1560 / 2422...
1570 / 2422...
1580 / 2422...
1590 / 2422...
1600 / 2422...
1610 / 2422...
1620 / 2422...
1630 / 2422...
1640 / 2422...
1650 / 2422...
1660 / 2422...
1670 / 2422...
1680 / 2422...
1690 / 2422...
1700 / 2422...
1710 / 2422...
1720 / 2422...
1730 / 2422...
1740 / 2422...
1750 / 2422...
1760 / 2422...
1770 / 2422...
1780 / 2422...
1790 / 2422...
1800 / 2422...
1810 / 2422...
1820 / 2422...
1830 / 2422...
1840 / 2422...
1850 / 2422...
1860 / 2422...
1870 / 2422...
1880 / 2422...
1890 / 2422...
1900 / 2422...
1910 / 2422...
1920 / 2422...
1930 / 2422...
1940 / 2422...
1950 / 2422...
1960 / 2422...
1970 / 2422...
1980 / 2422...
1990 / 2422...
2000 / 2422...
2010 / 2422...
2020 / 2422...
2030 / 2422...
2040 / 2422...
2050 / 2422...
2060 / 2422...
2070 / 2422...
2080 / 2422...
2090 / 2422...
2100 / 2422...
2110 / 2422...
2120 / 2422...
2130 / 2422...
2140 / 2422...
2150 / 2422...
2160 / 2422...
2170 / 2422...
2180 / 2422...
2190 / 2422...
2200 / 2422...
2210 / 2422...
2220 / 2422...
2230 / 2422...
2240 / 2422...
2250 / 2422...
2260 / 2422...
2270 / 2422...
2280 / 2422...
2290 / 2422...
2300 / 2422...
2310 / 2422...
2320 / 2422...
2330 / 2422...
2340 / 2422...
2350 / 2422...
2360 / 2422...
2370 / 2422...
2380 / 2422...
2390 / 2422...
2400 / 2422...
2410 / 2422...
2420 / 2422...
2422 / 2422...
2423 / 2423...
2430 / 2684...
2440 / 2684...
2450 / 2684...
2460 / 2684...
2470 / 2684...
2480 / 2684...
2490 / 2684...
2500 / 2684...
2510 / 2684...
2520 / 2684...
2530 / 2684...
2540 / 2684...
2550 / 2684...
2560 / 2684...
2570 / 2684...
2580 / 2684...
2590 / 2684...
2600 / 2684...
2610 / 2684...
2620 / 2684...
2630 / 2684...
2640 / 2684...
2650 / 2684...
2660 / 2684...
2670 / 2684...
2680 / 2684...
2684 / 2684...
2690 / 3200...
2700 / 3200...
2710 / 3200...
2720 / 3200...
2730 / 3200...
2740 / 3200...
2750 / 3200...
2760 / 3200...
2770 / 3200...
2780 / 3200...
2790 / 3200...
2800 / 3200...
2810 / 3200...
2820 / 3200...
2830 / 3200...
2840 / 3200...
2850 / 3200...
2860 / 3200...
2870 / 3200...
2880 / 3200...
2890 / 3200...
2900 / 3200...
2910 / 3200...
2920 / 3200...
2930 / 3200...
2940 / 3200...
2950 / 3200...
2960 / 3200...
2970 / 3200...
2980 / 3200...
2990 / 3200...
3000 / 3200...
3010 / 3200...
3020 / 3200...
3030 / 3200...
3040 / 3200...
3050 / 3200...
3060 / 3200...
3070 / 3200...
3080 / 3200...
3090 / 3200...
3100 / 3200...
3110 / 3200...
3120 / 3200...
3130 / 3200...
3140 / 3200...
3150 / 3200...
3160 / 3200...
3170 / 3200...
3180 / 3200...
3190 / 3200...
3200 / 3200...
3210 / 3742...
3220 / 3742...
3230 / 3742...
3240 / 3742...
3250 / 3742...
3260 / 3742...
3270 / 3742...
3280 / 3742...
3290 / 3742...
3300 / 3742...
3310 / 3742...
3320 / 3742...
3330 / 3742...
3340 / 3742...
3350 / 3742...
3360 / 3742...
3370 / 3742...
3380 / 3742...
3390 / 3742...
3400 / 3742...
3410 / 3742...
3420 / 3742...
3430 / 3742...
3440 / 3742...
3450 / 3742...
3460 / 3742...
3470 / 3742...
3480 / 3742...
3490 / 3742...
3500 / 3742...
3510 / 3742...
3520 / 3742...
3530 / 3742...
3540 / 3742...
3550 / 3742...
3560 / 3742...
3570 / 3742...
3580 / 3742...
3590 / 3742...
3600 / 3742...
3610 / 3742...
3620 / 3742...
3630 / 3742...
3640 / 3742...
3650 / 3742...
3660 / 3742...
3670 / 3742...
3680 / 3742...
3690 / 3742...
3700 / 3742...
3710 / 3742...
3720 / 3742...
3730 / 3742...
3740 / 3742...
3742 / 3742...
3750 / 4149...
3760 / 4149...
3770 / 4149...
3780 / 4149...
3790 / 4149...
3800 / 4149...
3810 / 4149...
3820 / 4149...
3830 / 4149...
3840 / 4149...
3850 / 4149...
3860 / 4149...
3870 / 4149...
3880 / 4149...
3890 / 4149...
3900 / 4149...
3910 / 4149...
3920 / 4149...
3930 / 4149...
3940 / 4149...
3950 / 4149...
3960 / 4149...
3970 / 4149...
3980 / 4149...
3990 / 4149...
4000 / 4149...
4010 / 4149...
4020 / 4149...
4030 / 4149...
4040 / 4149...
4050 / 4149...
4060 / 4149...
4070 / 4149...
4080 / 4149...
4090 / 4149...
4100 / 4149...
4110 / 4149...
4120 / 4149...
4130 / 4149...
4140 / 4149...
4149 / 4149...
4150 / 4406...
4160 / 4406...
4170 / 4406...
4180 / 4406...
4190 / 4406...
4200 / 4406...
4210 / 4406...
4220 / 4406...
4230 / 4406...
4240 / 4406...
4250 / 4406...
4260 / 4406...
4270 / 4406...
4280 / 4406...
4290 / 4406...
4300 / 4406...
4310 / 4406...
4320 / 4406...
4330 / 4406...
4340 / 4406...
4350 / 4406...
4360 / 4406...
4370 / 4406...
4380 / 4406...
4390 / 4406...
4400 / 4406...
4406 / 4406...
4410 / 4533...
4420 / 4533...
4430 / 4533...
4440 / 4533...
4450 / 4533...
4460 / 4533...
4470 / 4533...
4480 / 4533...
4490 / 4533...
4500 / 4533...
4510 / 4533...
4520 / 4533...
4530 / 4533...
4533 / 4533...
4540 / 4577...
4550 / 4577...
4560 / 4577...
4570 / 4577...
4577 / 4577...
4580 / 4588...
4588 / 4588...
4590 / 4605...
4600 / 4605...
4605 / 4605...

Analyzing files...

░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   60 / 1464 (4%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  120 / 1464 (8%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  180 / 1464 (12%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  240 / 1464 (16%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  300 / 1464 (20%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  360 / 1464 (24%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  420 / 1464 (28%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  480 / 1464 (32%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  540 / 1464 (36%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  600 / 1464 (40%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  660 / 1464 (45%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  720 / 1464 (49%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  780 / 1464 (53%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  840 / 1464 (57%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  900 / 1464 (61%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  960 / 1464 (65%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1020 / 1464 (69%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1080 / 1464 (73%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1140 / 1464 (77%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1200 / 1464 (81%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1260 / 1464 (86%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1320 / 1464 (90%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1380 / 1464 (94%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1440 / 1464 (98%)
░░░░░░░░░░░░░░░░░░░░░░░░

------------------------------
�[42;2m                              �[0m
�[42;30;2m       No errors found!       �[0m
�[42;2m                              �[0m
------------------------------
2628 other issues found.
You can display them with �[30;48;5;195m--show-info=true�[0m
------------------------------
Psalm can automatically fix 49 of these issues.
Run Psalm again with 
�[30;48;5;195m--alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockReturnType,MissingClosureReturnType,MissingParamType,ClassMustBeFinal --dry-run�[0m
to see what it can fix.
------------------------------

Checks took 18.67 seconds and used 1,364.331MB of memory
Psalm was able to infer types for 97.7946% of the codebase

@Kravalg

Kravalg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Code Review: PASS

Review Output
STATUS: PASS
0 issues.```
</details>

<details>
<summary>Verification Output</summary>

```text

Running on PHP 8.4.5, Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac.

JIT acceleration: OFF
You can enable JIT acceleration (experimental) with --force-jit.

Target PHP version: 8.4 (inferred from composer.json) Enabled extensions: dom, mongodb, simplexml.


Scanning files...


1 / 236...
10 / 236...
20 / 236...
30 / 236...
40 / 236...
50 / 236...
60 / 236...
70 / 236...
80 / 236...
90 / 236...
100 / 236...
110 / 236...
120 / 236...
130 / 236...
140 / 236...
150 / 236...
160 / 236...
170 / 236...
180 / 236...
190 / 236...
200 / 236...
210 / 236...
220 / 236...
230 / 236...
236 / 236...
240 / 301...
250 / 301...
260 / 301...
270 / 301...
280 / 301...
290 / 301...
300 / 301...
301 / 301...
310 / 633...
320 / 633...
330 / 633...
340 / 633...
350 / 633...
360 / 633...
370 / 633...
380 / 633...
390 / 633...
400 / 633...
410 / 633...
420 / 633...
430 / 633...
440 / 633...
450 / 633...
460 / 633...
470 / 633...
480 / 633...
490 / 633...
500 / 633...
510 / 633...
520 / 633...
530 / 633...
540 / 633...
550 / 633...
560 / 633...
570 / 633...
580 / 633...
590 / 633...
600 / 633...
610 / 633...
620 / 633...
630 / 633...
633 / 633...
640 / 805...
650 / 805...
660 / 805...
670 / 805...
680 / 805...
690 / 805...
700 / 805...
710 / 805...
720 / 805...
730 / 805...
740 / 805...
750 / 805...
760 / 805...
770 / 805...
780 / 805...
790 / 805...
800 / 805...
805 / 805...
810 / 872...
820 / 872...
830 / 872...
840 / 872...
850 / 872...
860 / 872...
870 / 872...
872 / 872...
880 / 902...
890 / 902...
900 / 902...
902 / 902...
910 / 920...
920 / 920...
930 / 953...
940 / 953...
950 / 953...
953 / 953...
956 / 956...
958 / 958...
960 / 2422...
970 / 2422...
980 / 2422...
990 / 2422...
1000 / 2422...
1010 / 2422...
1020 / 2422...
1030 / 2422...
1040 / 2422...
1050 / 2422...
1060 / 2422...
1070 / 2422...
1080 / 2422...
1090 / 2422...
1100 / 2422...
1110 / 2422...
1120 / 2422...
1130 / 2422...
1140 / 2422...
1150 / 2422...
1160 / 2422...
1170 / 2422...
1180 / 2422...
1190 / 2422...
1200 / 2422...
1210 / 2422...
1220 / 2422...
1230 / 2422...
1240 / 2422...
1250 / 2422...
1260 / 2422...
1270 / 2422...
1280 / 2422...
1290 / 2422...
1300 / 2422...
1310 / 2422...
1320 / 2422...
1330 / 2422...
1340 / 2422...
1350 / 2422...
1360 / 2422...
1370 / 2422...
1380 / 2422...
1390 / 2422...
1400 / 2422...
1410 / 2422...
1420 / 2422...
1430 / 2422...
1440 / 2422...
1450 / 2422...
1460 / 2422...
1470 / 2422...
1480 / 2422...
1490 / 2422...
1500 / 2422...
1510 / 2422...
1520 / 2422...
1530 / 2422...
1540 / 2422...
1550 / 2422...
1560 / 2422...
1570 / 2422...
1580 / 2422...
1590 / 2422...
1600 / 2422...
1610 / 2422...
1620 / 2422...
1630 / 2422...
1640 / 2422...
1650 / 2422...
1660 / 2422...
1670 / 2422...
1680 / 2422...
1690 / 2422...
1700 / 2422...
1710 / 2422...
1720 / 2422...
1730 / 2422...
1740 / 2422...
1750 / 2422...
1760 / 2422...
1770 / 2422...
1780 / 2422...
1790 / 2422...
1800 / 2422...
1810 / 2422...
1820 / 2422...
1830 / 2422...
1840 / 2422...
1850 / 2422...
1860 / 2422...
1870 / 2422...
1880 / 2422...
1890 / 2422...
1900 / 2422...
1910 / 2422...
1920 / 2422...
1930 / 2422...
1940 / 2422...
1950 / 2422...
1960 / 2422...
1970 / 2422...
1980 / 2422...
1990 / 2422...
2000 / 2422...
2010 / 2422...
2020 / 2422...
2030 / 2422...
2040 / 2422...
2050 / 2422...
2060 / 2422...
2070 / 2422...
2080 / 2422...
2090 / 2422...
2100 / 2422...
2110 / 2422...
2120 / 2422...
2130 / 2422...
2140 / 2422...
2150 / 2422...
2160 / 2422...
2170 / 2422...
2180 / 2422...
2190 / 2422...
2200 / 2422...
2210 / 2422...
2220 / 2422...
2230 / 2422...
2240 / 2422...
2250 / 2422...
2260 / 2422...
2270 / 2422...
2280 / 2422...
2290 / 2422...
2300 / 2422...
2310 / 2422...
2320 / 2422...
2330 / 2422...
2340 / 2422...
2350 / 2422...
2360 / 2422...
2370 / 2422...
2380 / 2422...
2390 / 2422...
2400 / 2422...
2410 / 2422...
2420 / 2422...
2422 / 2422...
2423 / 2423...
2430 / 2684...
2440 / 2684...
2450 / 2684...
2460 / 2684...
2470 / 2684...
2480 / 2684...
2490 / 2684...
2500 / 2684...
2510 / 2684...
2520 / 2684...
2530 / 2684...
2540 / 2684...
2550 / 2684...
2560 / 2684...
2570 / 2684...
2580 / 2684...
2590 / 2684...
2600 / 2684...
2610 / 2684...
2620 / 2684...
2630 / 2684...
2640 / 2684...
2650 / 2684...
2660 / 2684...
2670 / 2684...
2680 / 2684...
2684 / 2684...
2690 / 3200...
2700 / 3200...
2710 / 3200...
2720 / 3200...
2730 / 3200...
2740 / 3200...
2750 / 3200...
2760 / 3200...
2770 / 3200...
2780 / 3200...
2790 / 3200...
2800 / 3200...
2810 / 3200...
2820 / 3200...
2830 / 3200...
2840 / 3200...
2850 / 3200...
2860 / 3200...
2870 / 3200...
2880 / 3200...
2890 / 3200...
2900 / 3200...
2910 / 3200...
2920 / 3200...
2930 / 3200...
2940 / 3200...
2950 / 3200...
2960 / 3200...
2970 / 3200...
2980 / 3200...
2990 / 3200...
3000 / 3200...
3010 / 3200...
3020 / 3200...
3030 / 3200...
3040 / 3200...
3050 / 3200...
3060 / 3200...
3070 / 3200...
3080 / 3200...
3090 / 3200...
3100 / 3200...
3110 / 3200...
3120 / 3200...
3130 / 3200...
3140 / 3200...
3150 / 3200...
3160 / 3200...
3170 / 3200...
3180 / 3200...
3190 / 3200...
3200 / 3200...
3210 / 3742...
3220 / 3742...
3230 / 3742...
3240 / 3742...
3250 / 3742...
3260 / 3742...
3270 / 3742...
3280 / 3742...
3290 / 3742...
3300 / 3742...
3310 / 3742...
3320 / 3742...
3330 / 3742...
3340 / 3742...
3350 / 3742...
3360 / 3742...
3370 / 3742...
3380 / 3742...
3390 / 3742...
3400 / 3742...
3410 / 3742...
3420 / 3742...
3430 / 3742...
3440 / 3742...
3450 / 3742...
3460 / 3742...
3470 / 3742...
3480 / 3742...
3490 / 3742...
3500 / 3742...
3510 / 3742...
3520 / 3742...
3530 / 3742...
3540 / 3742...
3550 / 3742...
3560 / 3742...
3570 / 3742...
3580 / 3742...
3590 / 3742...
3600 / 3742...
3610 / 3742...
3620 / 3742...
3630 / 3742...
3640 / 3742...
3650 / 3742...
3660 / 3742...
3670 / 3742...
3680 / 3742...
3690 / 3742...
3700 / 3742...
3710 / 3742...
3720 / 3742...
3730 / 3742...
3740 / 3742...
3742 / 3742...
3750 / 4149...
3760 / 4149...
3770 / 4149...
3780 / 4149...
3790 / 4149...
3800 / 4149...
3810 / 4149...
3820 / 4149...
3830 / 4149...
3840 / 4149...
3850 / 4149...
3860 / 4149...
3870 / 4149...
3880 / 4149...
3890 / 4149...
3900 / 4149...
3910 / 4149...
3920 / 4149...
3930 / 4149...
3940 / 4149...
3950 / 4149...
3960 / 4149...
3970 / 4149...
3980 / 4149...
3990 / 4149...
4000 / 4149...
4010 / 4149...
4020 / 4149...
4030 / 4149...
4040 / 4149...
4050 / 4149...
4060 / 4149...
4070 / 4149...
4080 / 4149...
4090 / 4149...
4100 / 4149...
4110 / 4149...
4120 / 4149...
4130 / 4149...
4140 / 4149...
4149 / 4149...
4150 / 4406...
4160 / 4406...
4170 / 4406...
4180 / 4406...
4190 / 4406...
4200 / 4406...
4210 / 4406...
4220 / 4406...
4230 / 4406...
4240 / 4406...
4250 / 4406...
4260 / 4406...
4270 / 4406...
4280 / 4406...
4290 / 4406...
4300 / 4406...
4310 / 4406...
4320 / 4406...
4330 / 4406...
4340 / 4406...
4350 / 4406...
4360 / 4406...
4370 / 4406...
4380 / 4406...
4390 / 4406...
4400 / 4406...
4406 / 4406...
4410 / 4533...
4420 / 4533...
4430 / 4533...
4440 / 4533...
4450 / 4533...
4460 / 4533...
4470 / 4533...
4480 / 4533...
4490 / 4533...
4500 / 4533...
4510 / 4533...
4520 / 4533...
4530 / 4533...
4533 / 4533...
4540 / 4577...
4550 / 4577...
4560 / 4577...
4570 / 4577...
4577 / 4577...
4580 / 4588...
4588 / 4588...
4590 / 4605...
4600 / 4605...
4605 / 4605...

Analyzing files...

░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   60 / 1464 (4%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  120 / 1464 (8%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  180 / 1464 (12%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  240 / 1464 (16%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  300 / 1464 (20%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  360 / 1464 (24%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  420 / 1464 (28%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  480 / 1464 (32%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  540 / 1464 (36%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  600 / 1464 (40%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  660 / 1464 (45%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  720 / 1464 (49%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  780 / 1464 (53%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  840 / 1464 (57%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  900 / 1464 (61%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  960 / 1464 (65%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1020 / 1464 (69%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1080 / 1464 (73%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1140 / 1464 (77%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1200 / 1464 (81%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1260 / 1464 (86%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1320 / 1464 (90%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1380 / 1464 (94%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1440 / 1464 (98%)
░░░░░░░░░░░░░░░░░░░░░░░░

------------------------------
�[42;2m                              �[0m
�[42;30;2m       No errors found!       �[0m
�[42;2m                              �[0m
------------------------------
2630 other issues found.
You can display them with �[30;48;5;195m--show-info=true�[0m
------------------------------
Psalm can automatically fix 49 of these issues.
Run Psalm again with 
�[30;48;5;195m--alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockReturnType,MissingClosureReturnType,MissingParamType,ClassMustBeFinal --dry-run�[0m
to see what it can fix.
------------------------------

Checks took 16.78 seconds and used 1,364.987MB of memory
Psalm was able to infer types for 97.7920% of the codebase

@Kravalg

Kravalg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Code Review: PASS

Review Output
STATUS: PASS
0 issues.```
</details>

<details>
<summary>Verification Output</summary>

```text
make[1]: Entering directory '/home/kravtsov/Projects/user-service-issue217'
docker compose exec -e APP_ENV=test php ./vendor/bin/phpmd src ansi codesize,design,cleancode --exclude vendor
PHP Deprecated:  PHPMD\Rule\CleanCode\BooleanArgumentFlag::isBooleanValue(): Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/phpmd/phpmd/src/main/php/PHPMD/Rule/CleanCode/BooleanArgumentFlag.php on line 77

Deprecated: PHPMD\Rule\CleanCode\BooleanArgumentFlag::isBooleanValue(): Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/phpmd/phpmd/src/main/php/PHPMD/Rule/CleanCode/BooleanArgumentFlag.php on line 77
PHP Deprecated:  PHPMD\Report::__construct(): Implicitly marking parameter $baselineValidator as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/phpmd/phpmd/src/main/php/PHPMD/Report.php on line 61

Deprecated: PHPMD\Report::__construct(): Implicitly marking parameter $baselineValidator as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/phpmd/phpmd/src/main/php/PHPMD/Report.php on line 61
PHP Deprecated:  PDepend\Source\Language\PHP\PHPBuilder::buildEnum(): Implicitly marking parameter $type as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/PHPBuilder.php on line 2592
PHP Deprecated:  PDepend\Source\Language\PHP\PHPBuilder::buildEnumCase(): Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/PHPBuilder.php on line 2612

Deprecated: PDepend\Source\Language\PHP\PHPBuilder::buildEnum(): Implicitly marking parameter $type as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/PHPBuilder.php on line 2592

Deprecated: PDepend\Source\Language\PHP\PHPBuilder::buildEnumCase(): Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/PHPBuilder.php on line 2612
PHP Deprecated:  PDepend\Source\Language\PHP\AbstractPHPParser::setNodePositionsAndReturn(): Implicitly marking parameter $tokens as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php on line 2388

Deprecated: PDepend\Source\Language\PHP\AbstractPHPParser::setNodePositionsAndReturn(): Implicitly marking parameter $tokens as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php on line 2388
PHP Deprecated:  PDepend\Source\Language\PHP\AbstractPHPParser::throwUnexpectedTokenException(): Implicitly marking parameter $token as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php on line 8073

Deprecated: PDepend\Source\Language\PHP\AbstractPHPParser::throwUnexpectedTokenException(): Implicitly marking parameter $token as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php on line 8073
PHP Deprecated:  PDepend\Source\AST\ASTArtifactList\CollectionArtifactFilter::setFilter(): Implicitly marking parameter $filter as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/AST/ASTArtifactList/CollectionArtifactFilter.php on line 103

Deprecated: PDepend\Source\AST\ASTArtifactList\CollectionArtifactFilter::setFilter(): Implicitly marking parameter $filter as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/AST/ASTArtifactList/CollectionArtifactFilter.php on line 103
PHP Deprecated:  PDepend\Metrics\Analyzer\CouplingAnalyzer::calculateCoupling(): Implicitly marking parameter $coupledType as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Metrics/Analyzer/CouplingAnalyzer.php on line 378

Deprecated: PDepend\Metrics\Analyzer\CouplingAnalyzer::calculateCoupling(): Implicitly marking parameter $coupledType as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Metrics/Analyzer/CouplingAnalyzer.php on line 378

Found 0 violations and 0 errors in 3710ms

�[32mNo mess detected�[0m
docker compose exec -e APP_ENV=test php ./vendor/bin/phpmd tests ansi phpmd.tests.xml --exclude vendor,tests/CLI/bats/php
PHP Deprecated:  PHPMD\Rule\CleanCode\BooleanArgumentFlag::isBooleanValue(): Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/phpmd/phpmd/src/main/php/PHPMD/Rule/CleanCode/BooleanArgumentFlag.php on line 77

Deprecated: PHPMD\Rule\CleanCode\BooleanArgumentFlag::isBooleanValue(): Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/phpmd/phpmd/src/main/php/PHPMD/Rule/CleanCode/BooleanArgumentFlag.php on line 77
PHP Deprecated:  PHPMD\Report::__construct(): Implicitly marking parameter $baselineValidator as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/phpmd/phpmd/src/main/php/PHPMD/Report.php on line 61

Deprecated: PHPMD\Report::__construct(): Implicitly marking parameter $baselineValidator as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/phpmd/phpmd/src/main/php/PHPMD/Report.php on line 61
PHP Deprecated:  PDepend\Source\Language\PHP\PHPBuilder::buildEnum(): Implicitly marking parameter $type as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/PHPBuilder.php on line 2592
PHP Deprecated:  PDepend\Source\Language\PHP\PHPBuilder::buildEnumCase(): Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/PHPBuilder.php on line 2612

Deprecated: PDepend\Source\Language\PHP\PHPBuilder::buildEnum(): Implicitly marking parameter $type as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/PHPBuilder.php on line 2592

Deprecated: PDepend\Source\Language\PHP\PHPBuilder::buildEnumCase(): Implicitly marking parameter $value as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/PHPBuilder.php on line 2612
PHP Deprecated:  PDepend\Source\Language\PHP\AbstractPHPParser::setNodePositionsAndReturn(): Implicitly marking parameter $tokens as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php on line 2388

Deprecated: PDepend\Source\Language\PHP\AbstractPHPParser::setNodePositionsAndReturn(): Implicitly marking parameter $tokens as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php on line 2388
PHP Deprecated:  PDepend\Source\Language\PHP\AbstractPHPParser::throwUnexpectedTokenException(): Implicitly marking parameter $token as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php on line 8073

Deprecated: PDepend\Source\Language\PHP\AbstractPHPParser::throwUnexpectedTokenException(): Implicitly marking parameter $token as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/Language/PHP/AbstractPHPParser.php on line 8073

Deprecated: PDepend\Source\AST\ASTArtifactList\CollectionArtifactFilter::setFilter(): Implicitly marking parameter $filter as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/AST/ASTArtifactList/CollectionArtifactFilter.php on line 103
PHP Deprecated:  PDepend\Source\AST\ASTArtifactList\CollectionArtifactFilter::setFilter(): Implicitly marking parameter $filter as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Source/AST/ASTArtifactList/CollectionArtifactFilter.php on line 103
PHP Deprecated:  PDepend\Metrics\Analyzer\CouplingAnalyzer::calculateCoupling(): Implicitly marking parameter $coupledType as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Metrics/Analyzer/CouplingAnalyzer.php on line 378

Deprecated: PDepend\Metrics\Analyzer\CouplingAnalyzer::calculateCoupling(): Implicitly marking parameter $coupledType as nullable is deprecated, the explicit nullable type must be used instead in /srv/app/vendor/pdepend/pdepend/src/main/php/PDepend/Metrics/Analyzer/CouplingAnalyzer.php on line 378

Found 0 violations and 0 errors in 22148ms

�[32mNo mess detected�[0m
docker compose exec -e APP_ENV=test php ./vendor/bin/phpinsights --no-interaction --flush-cache --fix --ansi --disable-security-check

   0/713 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░]   0%
�[1G�[2K�[1A�[1G�[2K  89/713 [▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░]  12%
�[1G�[2K�[1A�[1G�[2K 178/713 [▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░]  24%
�[1G�[2K�[1A�[1G�[2K 267/713 [▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░]  37%
�[1G�[2K�[1A�[1G�[2K 352/713 [▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░]  49%
�[1G�[2K�[1A�[1G�[2K 441/713 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░]  61%
�[1G�[2K�[1A�[1G�[2K 530/713 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░]  74%
�[1G�[2K�[1A�[1G�[2K 619/713 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░]  86%
�[1G�[2K�[1A�[1G�[2K 708/713 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░]  99%
�[1G�[2K�[1A�[1G�[2K 712/713 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░]  99%
�[1G�[2K�[1A�[1G�[2K 713/713 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
�[1G�[2K�[1A�[1G�[2K 713/713 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

�[32m ✨ Analysis Completed !�[39m

�[33m[2026-06-08 01:28:13]�[39m `/srv/app`

        �[42m         �[49m        �[42m         �[49m        �[42m         �[49m        �[42m         �[49m        
        �[37;42;1m  100 %  �[39;49;22m        �[37;42;1m  97.4%  �[39;49;22m        �[37;42;1m  100 %  �[39;49;22m        �[37;42;1m  100 %  �[39;49;22m        
        �[42m         �[49m        �[42m         �[49m        �[42m         �[49m        �[42m         �[49m        
                                                                            
          �[37;1mCode�[39;22m          �[37;1m Complexity�[39;22m     �[37;1m Architecture�[39;22m        �[37;1mStyle�[39;22m          


Score scale: �[31m◼�[39m 1-49 �[33m◼�[39m 50-79 �[32m◼�[39m 80-100

[CODE] �[32;1m100 pts�[39;22m within �[36;49;1m11348�[39;49;22m lines

Comments ...................................................... 29.5 %
Classes ....................................................... 37.8 %
Functions ...................................................... 0.0 %
Globally ...................................................... 32.7 %

[COMPLEXITY] �[32;1m97.4 pts�[39;22m with average of �[36;49;1m1.42�[39;49;22m cyclomatic complexity

[ARCHITECTURE] �[32;1m100 pts�[39;22m within �[36;49;1m708�[39;49;22m files

Classes ....................................................... 82.3 %
Interfaces .................................................... 17.1 %
Globally ....................................................... 0.6 %
Traits ......................................................... 0.0 %

[MISC] �[32;1m100 pts�[39;22m on coding style and �[32;1m0 security issues�[39;22m encountered

�[31m•�[39m [Complexity] �[39;49;1mHaving `classes` with total cyclomatic complexity more than 5 is prohibited - Consider refactoring�[39;49;22m:
  �[32m�]8;;phpstorm://open?file=/srv/app/src/User/Infrastructure/Repository/MongoDBRecoveryCodeRepository.php&line=0�\src/User/Infrastructure/Repository/MongoDBRecoveryCodeRepository.php�]8;;�\�[39m: 6 cyclomatic complexity
  �[32m�]8;;phpstorm://open?file=/srv/app/src/User/Infrastructure/Repository/MongoDBUserRepository.php&line=0�\src/User/Infrastructure/Repository/MongoDBUserRepository.php�]8;;�\�[39m: 22 cyclomatic complexity
  �[32m�]8;;phpstorm://open?file=/srv/app/src/User/Infrastructure/Repository/MongoDBWriteResultCounter.php&line=0�\src/User/Infrastructure/Repository/MongoDBWriteResultCounter.php�]8;;�\�[39m: 9 cyclomatic complexity
  �[31m+44 issues omitted�[39m

�[31m•�[39m [Complexity] �[39;49;1mHaving `methods` with cyclomatic complexity more than 5 is prohibited - Consider refactoring�[39;49;22m:
  �[32m�]8;;phpstorm://open?file=/srv/app/src/Shared/Infrastructure/Adapter/DualAuthenticator.php&line=0�\src/Shared/Infrastructure/Adapter/DualAuthenticator.php�]8;;�\�[39m:extractTokenRoles: 6 cyclomatic complexity
  �[32m�]8;;phpstorm://open?file=/srv/app/src/Shared/Infrastructure/Resolver/PublicAccessResolver.php&line=0�\src/Shared/Infrastructure/Resolver/PublicAccessResolver.php�]8;;�\�[39m:isPublic: 6 cyclomatic complexity
  �[32m�]8;;phpstorm://open?file=/srv/app/src/User/Application/Factory/RegisterUserBatchCommandFactory.php&line=0�\src/User/Application/Factory/RegisterUserBatchCommandFactory.php�]8;;�\�[39m:createInputCollection: 7 cyclomatic complexity
  �[31m+5 issues omitted�[39m

�[30;43m                                                                                �[39;49m
�[30;43m [WARNING] No more issue can be fixed automatically. 55 issues remaining        �[39;49m
�[30;43m                                                                                �[39;49m


  - Star or contribute to PHP Insights:
    �[1mhttps://github.com/nunomaduro/phpinsights�[22m
  - Sponsor the maintainers:
    �[1mhttps://github.com/sponsors/nunomaduro�[22m
  - Subscribe to my YouTube channel:
    �[1mhttps://www.youtube.com/@nunomaduro�[22m
docker compose exec -e APP_ENV=test php ./vendor/bin/phpinsights analyse tests --no-interaction --flush-cache --fix --disable-security-check --config-path=phpinsights-tests.php

   0/763 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░]   0%

  95/763 [▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░]  12%

 189/763 [▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░]  24%

 284/763 [▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░]  37%

 379/763 [▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░]  49%

 474/763 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░]  62%

 569/763 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░]  74%

 664/763 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░]  87%

 759/763 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░]  99%

 763/763 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%


[2026-06-08 01:29:02] `/srv/app/tests`

                                                                            
          100 %            97.8%            100 %            100 %          
                                                                            
                                                                            
          Code           Complexity      Architecture        Style          



[truncated after 160 lines]

@Kravalg

Kravalg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Code Review: PASS

Review Output
STATUS: PASS
0 issues.```
</details>

<details>
<summary>Verification Output</summary>

```text
make[1]: Entering directory '/home/kravtsov/Projects/user-service-issue217'
docker compose exec -T -e APP_ENV=test php sh -lc 'set -eu; \
	export XDEBUG_MODE=coverage; \
	rm -rf /tmp/infection; \
	mkdir -p /tmp/infection/coverage-xml; \
	php -d memory_limit=-1 ./vendor/bin/phpunit --testsuite=Unit --coverage-xml=/tmp/infection/coverage-xml --log-junit=/tmp/infection/junit.xml --order-by=defects,random; \
	php -d memory_limit=-1 ./vendor/bin/infection --configuration=infection.json5 --coverage=/tmp/infection --skip-initial-tests --test-framework-options="--testsuite=Unit" --show-mutations --log-verbosity=all -j4 --min-msi=100 --min-covered-msi=100 --with-uncovered'
PHPUnit 10.5.63 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.4.5 with Xdebug 3.5.1
Configuration: /srv/app/phpunit.xml.dist
Random Seed:   1780886367

.............................................................   61 / 2314 (  2%)
.............................................................  122 / 2314 (  5%)
.............................................................  183 / 2314 (  7%)
.............................................................  244 / 2314 ( 10%)
.............................................................  305 / 2314 ( 13%)
.............................................................  366 / 2314 ( 15%)
.............................................................  427 / 2314 ( 18%)
.............................................................  488 / 2314 ( 21%)
.............................................................  549 / 2314 ( 23%)
.............................................................  610 / 2314 ( 26%)
.............................................................  671 / 2314 ( 28%)
.............................................................  732 / 2314 ( 31%)
.............................................................  793 / 2314 ( 34%)
.............................................................  854 / 2314 ( 36%)
.............................................................  915 / 2314 ( 39%)
.............................................................  976 / 2314 ( 42%)
............................................................. 1037 / 2314 ( 44%)
............................................................. 1098 / 2314 ( 47%)
............................................................. 1159 / 2314 ( 50%)
............................................................. 1220 / 2314 ( 52%)
............................................................. 1281 / 2314 ( 55%)
............................................................. 1342 / 2314 ( 57%)
............................................................. 1403 / 2314 ( 60%)
............................................................. 1464 / 2314 ( 63%)
............................................................. 1525 / 2314 ( 65%)
............................................................. 1586 / 2314 ( 68%)
............................................................. 1647 / 2314 ( 71%)
............................................................. 1708 / 2314 ( 73%)
............................................................. 1769 / 2314 ( 76%)
............................................................. 1830 / 2314 ( 79%)
............................................................. 1891 / 2314 ( 81%)
............................................................. 1952 / 2314 ( 84%)
............................................................. 2013 / 2314 ( 86%)
............................................................. 2074 / 2314 ( 89%)
............................................................. 2135 / 2314 ( 92%)
............................................................. 2196 / 2314 ( 94%)
............................................................. 2257 / 2314 ( 97%)
.........................................................     2314 / 2314 (100%)

Time: 00:22.496, Memory: 160.50 MB

OK (2314 tests, 6565 assertions)

Generating code coverage report in PHPUnit XML format ... done [00:04.001]

    ____      ____          __  _
   /  _/___  / __/__  _____/ /_(_)___  ____
   / // __ \/ /_/ _ \/ ___/ __/ / __ \/ __ \
 _/ // / / / __/  __/ /__/ /_/ / /_/ / / / /
/___/_/ /_/_/  \___/\___/\__/_/\____/_/ /_/

#StandWithUkraine

Infection - PHP Mutation Testing Framework version 0.33.2

[notice] Running Infection with 4 threads.
[warning] Skipping the initial test run can be very dangerous.
It is your responsibility to ensure the tests are in a passing state to begin.
If this is not done then mutations may report as caught when they are not.

Generate mutants...

Processing source code files:   0/705
Processing source code files:  71/705
Processing source code files: 141/705
Processing source code files: 212/705
Processing source code files: 282/705
Processing source code files: 353/705
Processing source code files: 423/705
Processing source code files: 494/705
Processing source code files: 564/705
Processing source code files: 635/705
Processing source code files: 705/705
.: killed by tests, A: killed by SA, M: escaped, U: uncovered
E: fatal error, X: syntax error, T: timed out, S: skipped, I: ignored

..................................................   (  50 / 4782)
..................................................   ( 100 / 4782)
..................................................   ( 150 / 4782)
..................................................   ( 200 / 4782)
..................................................   ( 250 / 4782)
..................................................   ( 300 / 4782)
..................................................   ( 350 / 4782)
..................................................   ( 400 / 4782)
..................................................   ( 450 / 4782)
..................................................   ( 500 / 4782)
..................................................   ( 550 / 4782)
..................................................   ( 600 / 4782)
..................................................   ( 650 / 4782)
..................................................   ( 700 / 4782)
..................................................   ( 750 / 4782)
..................................................   ( 800 / 4782)
..................................................   ( 850 / 4782)
..................................................   ( 900 / 4782)
..................................................   ( 950 / 4782)
..................................................   (1000 / 4782)
..................................................   (1050 / 4782)
..................................................   (1100 / 4782)
..................................................   (1150 / 4782)
..................................................   (1200 / 4782)
..................................................   (1250 / 4782)
..................................................   (1300 / 4782)
..................................................   (1350 / 4782)
..................................................   (1400 / 4782)
..................................................   (1450 / 4782)
..................................................   (1500 / 4782)
..................................................   (1550 / 4782)
..................................................   (1600 / 4782)
..................................................   (1650 / 4782)
..................................................   (1700 / 4782)
..................................................   (1750 / 4782)
..................................................   (1800 / 4782)
..................................................   (1850 / 4782)
..................................................   (1900 / 4782)
..................................................   (1950 / 4782)
..................................................   (2000 / 4782)
..................................................   (2050 / 4782)
..................................................   (2100 / 4782)
..................................................   (2150 / 4782)
..................................................   (2200 / 4782)
..................................................   (2250 / 4782)
..................................................   (2300 / 4782)
..................................................   (2350 / 4782)
..................................................   (2400 / 4782)
..................................................   (2450 / 4782)
..................................................   (2500 / 4782)
..................................................   (2550 / 4782)
..................................................   (2600 / 4782)
..................................................   (2650 / 4782)
..................................................   (2700 / 4782)
..................................................   (2750 / 4782)
..................................................   (2800 / 4782)
..................................................   (2850 / 4782)
..................................................   (2900 / 4782)
..................................................   (2950 / 4782)
..................................................   (3000 / 4782)
..................................................   (3050 / 4782)
..................................................   (3100 / 4782)
..................................................   (3150 / 4782)
..................................................   (3200 / 4782)
..................................................   (3250 / 4782)
..................................................   (3300 / 4782)
..................................................   (3350 / 4782)
..................................................   (3400 / 4782)
..................................................   (3450 / 4782)
..................................................   (3500 / 4782)
..................................................   (3550 / 4782)

[truncated after 160 lines]

@Kravalg

Kravalg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

STATUS: PASS

Code Review passed for commit 985a55f1.

Verification evidence:

  • Local AI review loop: PASS
  • Local Infection verifier: 4782/4782 mutants killed, MSI 100%
  • GitHub status context: Code Review

@Kravalg

Kravalg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

BMAD FR/NFR Review Gate: FAIL

  • Commit: 985a55f1
  • Status context: BMAD FR/NFR Review Gate
  • Result: Unexpected AI review loop failure after pending publication (exit 1): cp "$fix_log" "$log_dir/fix-latest.md"
  • PR: Refactor registration command CQRS flow #282
Review Output
=== Agent: codex ===
STATUS: FAIL
Issues:
1. BMAD scope/readiness blocker: `specs/issue-217-register-user-cqrs/prd.md:43-46` requires preserving public behavior and keeping changes focused to registration/docs/tests, while `specs/issue-217-register-user-cqrs/implementation-readiness.md:22` says no database/schema/endpoint/infrastructure change is required. The PR changes domain state, ODM mapping/indexes, repository contracts, cache, Docker config, OAuth, password reset, 2FA, batch registration, and adds a backfill command.
2. Release/data-integrity blocker: `config/doctrine/User/User.mongodb.xml:13-29` adds a persisted `normalizedEmail` field and unique partial index, and `src/User/Infrastructure/Command/BackfillUserNormalizedEmailsCommand.php:24-57` adds a data backfill path, but there is no runbook, deployment order, rollback plan, production duplicate-resolution process, or integration evidence for real MongoDB index/backfill behavior.
3. Automated coverage blocker for expanded scope: unit tests cover many new classes, but the expanded cross-context behavior lacks required integration/E2E coverage for real ODM uniqueness/index creation, REST case-insensitive duplicate registration, OAuth auto-link ambiguity, password-reset/2FA duplicate-email lookup behavior, and backfill execution against MongoDB.

FR_NFR_SCORECARD: FAIL
NFR_CATALOG_SCORECARD: FAIL
EXPANDED_QUALITY_SCORECARD: FAIL
SYSTEM_QUALITY_ATTRIBUTES_SCORECARD: FAIL
WHOLE_CODEBASE_IMPACT: FAIL
GRAPH_IMPACT_CONTEXT: PASS
TEST_CASE_MATRIX: FAIL
AUTO_TEST_COVERAGE: FAIL
FLAKY_TEST_RISK: PASS
MANUAL_TEST_EVIDENCE: PASS
QA_BEST_PRACTICES: FAIL
GITHUB_COMPLETION_GATE: PASS
CI_GATE: PASS
FR_NFR_MIN_SCORE: 2/5
NFR_CATALOG_MIN_SCORE: 3/5
EXPANDED_QUALITY_MIN_SCORE: 3/5
SYSTEM_QUALITY_ATTRIBUTES_MIN_SCORE: 3/5
IMPACT_ANALYSIS_MIN_SCORE: 2/5
TEST_CASE_COVERAGE_MIN_SCORE: 3/5
AUTO_TEST_COVERAGE_MIN_SCORE: 3/5
FLAKY_TEST_RISK_MIN_SCORE: 5/5
GITHUB_COMPLETION_STATE: PASSING
GITHUB_HUMAN_APPROVAL_STATE: REVIEW_REQUIRED
CI_CHECK_ROLLUP: PASSING

Requirement Scorecard: source requirement, evidence, score, status
- FR1 immutable `RegisterUserCommand` input only: `src/User/Application/Command/RegisterUserCommand.php`, unit test, score 5/5 PASS.
- FR2 no command response mutation methods: `rg` found no `getResponse`/`setResponse` on register command, score 5/5 PASS.
- FR3 response DTO wraps created user: `RegisterUserCommandResponse::$user`, score 5/5 PASS.
- FR4 handler returns response, rejects duplicate before hash/save/event: `RegisterUserCommandHandler`, unit tests, score 5/5 PASS.
- FR5 lookup through query handler: `FindUserByEmailQueryHandlerInterface` alias and callers, score 5/5 PASS.
- FR6 REST processor uses shared dispatcher and guarded response: `RegisterUserProcessor`, score 5/5 PASS.
- FR7 GraphQL validates before dispatch and uses dispatcher: `RegisterUserMutationResolver`, Behat evidence, score 5/5 PASS.
- FR8 tests for command/handler/duplicate/guarding: unit + Behat + CI rollup, score 5/5 PASS.
- FR9 docs describe command response separation: `docs/design-and-architecture.md:55`, score 5/5 PASS.
- NFR focus/readiness: contradicted by domain/schema/infra/OAuth/2FA/password-reset/batch changes, score 2/5 FAIL.
- Readiness no DB/schema/infra change: contradicted by `User.mongodb.xml`, `MongoDBUserRepository`, Docker, backfill command, score 2/5 FAIL.

NFR Catalog Scorecard: every pinned NFR category with checked subdimensions, evidence or not-applicable reason, source, score, status
- Performance: checked lookup/index/cache/load evidence; K6 passed, but no targeted legacy/backfill/index benchmark; graph source repo/cache/docker edges; score 4/5 FAIL.
- Usability: checked API errors/localization/operator use; user errors covered, backfill operator docs absent; score 4/5 FAIL.
- Maintainability: checked scope/modularity/tests/static analysis; broad unplanned impact violates PRD focus; score 3/5 FAIL.
- Availability: checked rollout/recovery/failure modes; unique index/backfill has no rollout/rollback runbook; score 3/5 FAIL.
- Interoperability: checked REST/GraphQL/OpenAPI/GraphQL Inspector; public schema passes, but behavior expands into OAuth/auth flows without contract tests; score 4/5 FAIL.
- Security: checked auth/account enumeration/validation/Snyk; no account data exposed, but cross-auth duplicate ambiguity lacks integration evidence; score 4/5 FAIL.
- Manageability: checked metrics/logs/config/runbooks; new command/index lacks operational docs and alerting; score 3/5 FAIL.
- Automatability: checked CI/headless commands; backfill has unit tests but no CI integration execution evidence; score 4/5 FAIL.
- Dependability: checked correctness/data consistency/idempotency; normalized-email migration risks unresolved; score 3/5 FAIL.

Expanded Quality Scorecard: every pinned expanded quality dimension with checked subdimensions, evidence or not-applicable reason, source, score, status
- Functional Suitability: core CQRS behavior implemented; scope-expanded behavior not fully specified; score 4/5 FAIL.
- Performance Resource Sustainability: K6/cache checks pass; no backfill/index cost evidence; score 4/5 FAIL.
- Compatibility Coexistence: schema checks pass; DB/index compatibility rollout absent; score 3/5 FAIL.
- Interaction Capability Accessibility: API/localized errors covered; operator backfill guidance missing; score 4/5 FAIL.
- Reliability Resilience: duplicate/save failure covered; migration/backfill recovery not covered; score 3/5 FAIL.
- Security Privacy Accountability: validation/security scans pass; auth side-effects need integration evidence; score 4/5 FAIL.
- Maintainability Testability: many unit tests; broad unplanned coupling reduces traceability; score 3/5 FAIL.
- Flexibility Portability: Docker image env added; DB migration portability not documented; score 4/5 FAIL.
- Safety Harm Prevention: duplicate account harm partly mitigated; data-migration harm plan missing; score 3/5 FAIL.
- Data Quality Integrity: normalized uniqueness intended; backfill duplicate resolution/integration missing; score 3/5 FAIL.
- Operational Excellence Releaseability: no runbook/rollback/backfill release plan; score 3/5 FAIL.
- Observability Diagnosability: cache logs exist; no backfill metrics/audit artifacts; score 4/5 FAIL.
- Supply-Chain Integrity: no lockfile dependency change, Snyk success; score 5/5 PASS.
- Compliance Governance: PII email uniqueness changed without retention/audit release note; score 4/5 FAIL.
- Sustainability Resource Impact: no sustained backfill/load resource evidence; score 4/5 FAIL.
- AI Automation Governance: wrapper/GitHub evidence present; no unsafe writes from this review; score 5/5 PASS.

System Quality Attributes Scorecard: every pinned Wikipedia system quality attribute with checked meaning, evidence or concrete not-applicable reason, source, score, status, improvement recommendation
- Accessibility: API-only surface; localized error evidence; source features; score 5/5 PASS; Improvement: none.
- Accountability: audit/review evidence exists, migration audit missing; score 4/5 FAIL; Improvement: add backfill audit/runbook.
- Accuracy: email normalization correctness partly tested; real ODM index absent; score 4/5 FAIL; Improvement: add integration test.
- Adaptability: env Mongo image added; undocumented; score 4/5 FAIL; Improvement: document config.
- Administrability: new backfill command lacks ops docs; score 3/5 FAIL; Improvement: add runbook.
- Affordability: no new dependencies; backfill resource cost unmeasured; score 4/5 FAIL; Improvement: document bounded execution.
- Agility: CQRS improves changeability; broad scope hurts traceability; score 4/5 FAIL; Improvement: align spec or split PR.
- Analyzability: tests/graph present; scope mismatch impairs analysis; score 4/5 FAIL; Improvement: update BMAD impact docs.
- Auditability: CI/GitHub evidence present; data changes lack audit output; score 4/5 FAIL; Improvement: persist backfill report.
- Autonomy: automation evidence present; risky data action lacks guard docs; score 4/5 FAIL; Improvement: document operator approval.
- Availability: rollout/backfill recovery missing; score 3/5 FAIL; Improvement: release plan.
- Compatibility: public checks pass; DB compatibility unproven; score 3/5 FAIL; Improvement: migration verification.
- Composability: dispatcher/query abstractions okay; shared query side effects broad; score 4/5 FAIL; Improvement: specify shared contract.
- Confidentiality: no account data returned on duplicate; score 5/5 PASS; Improvement: none.
- Configurability: Mongo image configurable; undocumented; score 4/5 FAIL; Improvement: docs.
- Convenience: API callers unchanged; operators lack guidance; score 4/5 FAIL; Improvement: runbook.
- Correctness: core FRs pass; expanded persistence not fully verified; score 4/5 FAIL; Improvement: integration tests.
- Credibility: CI passes; BMAD traceability fails; score 4/5 FAIL; Improvement: reconcile specs.
- Customizability: N/A to current backend flow, no changed custom UI; source diff; score 5/5 PASS; Improvement: none.
- Debuggability: logs in cache, no backfill diagnostics artifact; score 4/5 FAIL; Improvement: structured command output.
- Degradability: duplicate failure handling exists, rollout degradation missing; score 3/5 FAIL; Improvement: fallback/rollback plan.
- Determinability: deterministic command flow; backfill ordering exists; no integration proof; score 4/5 FAIL; Improvement: integration evidence.
- Demonstrability: unit/CI evidence high; manual/release demo absent for DB; score 4/5 FAIL; Improvement: attach run output.
- Dependability: data integrity gap; score 3/5 FAIL; Improvement: migration tests.
- Deployability: schema/index/backfill no deploy order; score 3/5 FAIL; Improvement: deploy checklist.
- Discoverability: docs mention CQRS only; new command undiscoverable in docs; score 4/5 FAIL; Improvement: operational docs.
- Distributability: Docker config changed; no multi-env proof; score 4/5 FAIL; Improvement: env matrix.
- Durability: normalized email persistence added; backfill durability unproven; score 3/5 FAIL; Improvement: DB integration.
- Effectiveness: core user registration outcome works; expanded scope unresolved; score 4/5 FAIL; Improvement: reduce scope.
- Efficiency: no targeted query/backfill metrics; score 4/5 FAIL; Improvement: benchmark.
- Elasticity: N/A beyond DB/load stack; K6 pass; score 5/5 PASS; Improvement: none.
- Evolvability: abstractions help; domain/schema surprise hurts; score 4/5 FAIL; Improvement: spec update.
- Extensibility: query interface helps; shared exception semantics need contract; score 4/5 FAIL; Improvement: document interface behavior.
- Failure Transparency: duplicate/backfill errors exist; no ops artifact; score 4/5 FAIL; Improvement: log/report duplicates.
- Familiarity: CQRS pattern consistent; broad side effects surprising; score 4/5 FAIL; Improvement: split/refine.
- Fault-Tolerance: save duplicate handling; migration failure plan absent; score 3/5 FAIL; Improvement: rollback plan.
- Fidelity: public API mostly preserved; duplicate localization covered; score 5/5 PASS; Improvement: none.
- Flexibility: Docker env plus service abstractions; DB portability gap; score 4/5 FAIL; Improvement: docs.
- Inspectability: graph/diff/tests inspected; backfill lacks report file; score 4/5 FAIL; Improvement: command evidence.
- Installability: no dependency changes; DB index rollout not documented; score 4/5 FAIL; Improvement: install/deploy note.
- Integrity: uniqueness intended; data migration gap; score 3/5 FAIL; Improvement: integration and runbook.
- Interactivity: API-only; automated GraphQL interaction covered; score 5/5 PASS; Improvement: none.
- Interchangeability: repository interface changed; adapters updated; contract tests incomplete; score 4/5 FAIL; Improvement: repository contract tests.
- Interoperability: API checks pass, auth/OAuth expansion lacks E2E; score 4/5 FAIL; Improvement: E2E.
- Intuitiveness: API error text clear; ops command undocumented; score 4/5 FAIL; Improvement: command docs.
- Learnability: docs updated for CQRS; not for normalized email; score 4/5 FAIL; Improvement: docs.
- Localizability: EN/UK duplicate messages covered; score 5/5 PASS; Improvement: none.
- Maintainability: scope mismatch; score 3/5 FAIL; Improvement: split/update spec.
- Manageability: missing runbook/metrics; score 3/5 FAIL; Improvement: ops docs.
- Mobility: N/A to service backend; no mobile surface changed; score 5/5 PASS; Improvement: none.
- Modifiability: abstractions help; broad shared query coupling; score 4/5 FAIL; Improvement: contract docs.
- Modularity: DDD layers mostly respected; domain changed contrary to spec; score 4/5 FAIL; Improvement: align architecture.
- Observability: CI/logs okay; backfill observability weak; score 4/5 FAIL; Improvement: metrics/report.
- Operability: command exists; no operator workflow; score 3/5 FAIL; Improvement: runbook.
- Orthogonality: unrelated Docker/OAuth/2FA changes reduce independence; score 3/5 FAIL; Improvement: split PR.
- Portability: no dependency change; Mongo-specific index/backfill docs missing; score 4/5 FAIL; Improvement: document Mongo assumptions.
- Precision: duplicate matching precise in unit tests; real DB regex/index not verified; score 4/5 FAIL; Improvement: integration.
- Predictability: command flow predictable; deployment effects not; score 3/5 FAIL; Improvement: rollout plan.
- Process Capabilities: CI strong; BMAD gate traceability weak; score 4/5 FAIL; Improvement: update spec.
- Producibility: build/checks pass; reproducible DB migration not shown; score 4/5 FAIL; Improvement: migration script evidence.
- Provability: unit/mutation pass; integration proof missing; score 3/5 FAIL; Improvement: add tests.
- Recoverability: no rollback/duplicate resolution plan; score 3/5 FAIL; Improvement: runbook.
- Redundancy: N/A to single-service change; no redundancy surface changed; score 5/5 PASS; Improvement: none.
- Relevance: core CQRS relevant; extra scope partially irrelevant to BMAD; score 3/5 FAIL; Improvement: trim scope.
- Reliability: CI pass; data rollout risk; score 3/5 FAIL; Improvement: integration/release evidence.
- Repairability: backfill can abort on duplicates; no repair steps; score 3/5 FAIL; Improvement: duplicate-resolution guide.
- Repeatability: CI repeatable; backfill production repeatability undocumented; score 4/5 FAIL; Improvement: dry-run/report mode.
- Reproducibility: tests reproducible enough; DB state reproduction missing; score 4/5 FAIL; Improvement: fixture/integration.
- Resilience: save failures handled; release resilience missing; score 3/5 FAIL; Improvement: rollback.
- Responsiveness: no targeted latency evidence for added lookup path; score 4/5 FAIL; Improvement: benchmark.
- Reusability: dispatcher/query reusable; shared exception behavior needs docs; score 4/5 FAIL; Improvement: contract.
- Robustness: negative tests exist; missing real DB edge tests; score 4/5 FAIL; Improvement: integration.
- Safety: account duplication harm mitigated; migration harm unresolved; score 3/5 FAIL; Improvement: safety checklist.
- Scalability: index helps lookups; backfill scale unmeasured; score 4/5 FAIL; Improvement: volume test.
- Seamlessness: public API likely preserved; deployment not seamless; score 3/5 FAIL; Improvement: migration plan.
- Self-Sustainability: no ongoing ops burden docs; score 4/5 FAIL; Improvement: runbook.
- Serviceability: support diagnostics for backfill absent; score 3/5 FAIL; Improvement: diagnostics.
- Securability: validation/security scans pass; auth integration gap; score 4/5 FAIL; Improvement: auth E2E.
- Simplicity: core command simpler; PR breadth complex; score 3/5 FAIL; Improvement: split.
- Stability: CI pass; schema rollout unstable risk; score 3/5 FAIL; Improvement: staged release.
- Standards Compliance: Deptrac/Psalm/Spectral pass; score 5/5 PASS; Improvement: none.
- Survivability: no disaster/recovery impact evidence for DB change; score 3/5 FAIL; Improvement: rollback.
- Sustainability: resource impact of backfill unmeasured; score 4/5 FAIL; Improvement: resource note.
- Tailorability: N/A beyond config; no user tailoring changed; score 5/5 PASS; Improvement: none.
- Testability: many units; missing integration classes; score 3/5 FAIL; Improvement: add integration/E2E.

[truncated after 160 lines]

Comment thread tests/Integration/Auth/EmailAmbiguityRuntimeIntegrationTest.php Outdated
Comment thread tests/Integration/Auth/EmailAmbiguityRuntimeIntegrationTest.php Outdated
Comment thread tests/Integration/User/Application/Processor/RegisterUserRestIntegrationTest.php Outdated
@Kravalg

Kravalg commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

BMAD FR/NFR Review Gate: FAIL

Review Output
=== Agent: codex ===
STATUS: FAIL
Issues:
1. CI is not passing. GitHub run `27120150113` failed in job `symfony-checks`, step `Install Symfony CLI`; multiple applicable PR checks are still queued or in progress, including PHPUnit, Schemathesis, Behat/E2E, mutation, load, OpenAPI, GraphQL, PHPInsights, cache performance, and memory leak checks.
2. GitHub completion is blocked. PR 282 is not draft and the head matches `1d9d737f560658122c10759c527d71bf7973eaee`, but review state is `REVIEW_REQUIRED` and active unresolved qlty review threads remain in changed test files.
3. Manual evidence is absent. Input says `NOT_PROVIDED`, while the BMAD readiness source requires production-rollout evidence including a backfill dry-run JSON report, duplicate-remediation review, and rollout/rollback checklist evidence.
4. Mandatory local verification is not evidenced. I could not verify completed `make ci`, `make ai-review-loop`, or the BMAD review wrapper in this read-only sandbox; current GitHub CI is also failed/pending.
5. Data-normalization consistency is not fully clean: `UserCredentialValidator.php` and `CachedUserRepository.php` still use local `strtolower(trim())` normalization instead of the shared `EmailNormalizer`, leaving avoidable Unicode/case consistency risk.

FR_NFR_SCORECARD: FAIL
NFR_CATALOG_SCORECARD: FAIL
EXPANDED_QUALITY_SCORECARD: FAIL
SYSTEM_QUALITY_ATTRIBUTES_SCORECARD: FAIL
WHOLE_CODEBASE_IMPACT: FAIL
GRAPH_IMPACT_CONTEXT: PASS
TEST_CASE_MATRIX: FAIL
AUTO_TEST_COVERAGE: FAIL
FLAKY_TEST_RISK: FAIL
MANUAL_TEST_EVIDENCE: FAIL
QA_BEST_PRACTICES: FAIL
GITHUB_COMPLETION_GATE: FAIL
CI_GATE: FAIL

FR_NFR_MIN_SCORE: 3/5
NFR_CATALOG_MIN_SCORE: 3/5
EXPANDED_QUALITY_MIN_SCORE: 3/5
SYSTEM_QUALITY_ATTRIBUTES_MIN_SCORE: 3/5
IMPACT_ANALYSIS_MIN_SCORE: 3/5
TEST_CASE_COVERAGE_MIN_SCORE: 3/5
AUTO_TEST_COVERAGE_MIN_SCORE: 2/5
FLAKY_TEST_RISK_MIN_SCORE: 4/5
GITHUB_COMPLETION_STATE: FAILING
GITHUB_HUMAN_APPROVAL_STATE: REVIEW_REQUIRED
CI_CHECK_ROLLUP: FAILING

Requirement Scorecard: source requirement, evidence, score, status
- FR1-FR3 immutable `RegisterUserCommand` and response DTO: `src/User/Application/Command/RegisterUserCommand.php`, `src/User/Application/DTO/RegisterUserCommandResponse.php`; tests present; CI not complete. Score 4/5 FAIL.
- FR4-FR8 handler/processor/resolver CQRS flow and duplicate guard: `RegisterUserCommandHandler`, `RegisterUserCommandDispatcher`, REST/GraphQL processor/resolver tests; CI not complete. Score 4/5 FAIL.
- FR9 docs: `docs/design-and-architecture.md` updated. Score 5/5 PASS.
- FR10-FR12 normalized email persistence/repository/query ambiguity: Mongo mapping, repository, query handler, integration/unit tests present; CI not complete. Score 4/5 FAIL.
- FR13-FR16 REST/OAuth/password-reset/2FA ambiguity behavior: implementation and integration tests present; CI not complete. Score 4/5 FAIL.
- FR17 backfill command/runbook/reporting: code, tests, and docs present; required manual dry-run artifact not provided. Score 3/5 FAIL.
- NFR public compatibility/static architecture/automation: OpenAPI diff and Deptrac checks passed, but full PR check rollup failed/pending. Score 3/5 FAIL.

NFR Catalog Scorecard: every pinned NFR category with checked subdimensions, evidence or not-applicable reason, source, score, status
- Performance: checked latency/load/cache/query/index impact; cache/index code exists, load/cache CI pending. Source PRD + NonFunctionals catalog. Score 3/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))
- Usability: checked API errors, neutral 204, 409 problem response, docs/operator usability; CI/manual evidence missing. Score 3/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))
- Maintainability: checked CQRS split, tests, architecture, review comments; unresolved qlty threads and normalization inconsistency remain. Score 3/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))
- Availability: checked safe duplicate failure, no token/secret/link mutation, backfill abort; resilience checks pending. Score 3/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))
- Interoperability: checked REST/GraphQL/OpenAPI/OAuth contracts; OpenAPI diff passed, Schemathesis/GraphQL pending. Score 3/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))
- Security: checked auth ambiguity, token/session/cookie suppression, Snyk pass; security-relevant tests pending. Score 4/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))
- Manageability: checked backfill command, JSON report, runbook, CI evidence; manual report absent. Score 3/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))
- Automatability: checked make/CI/test automation, deterministic command; CI failed/pending and ai-review-loop not evidenced. Score 2/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))
- Dependability: checked correctness, safe failure, duplicate guard, rollback docs; full verification incomplete. Score 3/5 FAIL. ([nonfunctionals.com](https://nonfunctionals.com/catalog.html?utm_source=openai))

Expanded Quality Scorecard: every pinned expanded quality dimension with checked subdimensions, evidence or not-applicable reason, source, score, status
- Functional Suitability: CQRS and duplicate behavior implemented; verification pending. Score 4/5 FAIL.
- Performance Resource Sustainability: indexes/cache/backfill batching checked; load/cache CI pending. Score 3/5 FAIL.
- Compatibility Coexistence: legacy fallback/OpenAPI checked; contract checks pending. Score 4/5 FAIL.
- Interaction Capability Accessibility: API error behavior/docs checked; manual/contract evidence incomplete. Score 3/5 FAIL.
- Reliability Resilience: safe failure paths implemented; integration CI pending. Score 3/5 FAIL.
- Security Privacy Accountability: ambiguity protects tokens/cookies/secrets; tests pending. Score 4/5 FAIL.
- Maintainability Testability: tests broad, but unresolved qlty threads remain. Score 3/5 FAIL.
- Flexibility Portability: Docker Mongo image configurable; install/check workflow failed. Score 3/5 FAIL.
- Safety Harm Prevention: no state mutation tests exist; CI pending. Score 4/5 FAIL.
- Data Quality Integrity: normalized email/index/backfill implemented; manual artifact absent. Score 3/5 FAIL.
- Operational Excellence Releaseability: runbook exists; rollout evidence absent. Score 3/5 FAIL.
- Observability Diagnosability: JSON report exists; no completed artifact or alert evidence. Score 3/5 FAIL.
- Supply-Chain Integrity: no lockfile change; Snyk pass; install workflow failed. Score 4/5 FAIL.
- Compliance Governance: privacy/security behavior in scope; no approval/manual record. Score 3/5 FAIL.
- Sustainability Resource Impact: bounded index/cache/backfill considered; load evidence pending. Score 3/5 FAIL.
- AI Automation Governance: review gate allowed, but ai-review-loop/BMAD completion absent. Score 2/5 FAIL.

System Quality Attributes Scorecard: every pinned Wikipedia system quality attribute with checked meaning, evidence or concrete not-applicable reason, source, score, status, improvement recommendation
Source model: wrapper-pinned list was cross-checked against the current Wikipedia quality-attribute list; no pinned attribute was missing from the page. ([en.wikipedia.org](https://en.wikipedia.org/wiki/List_of_system_quality_attributes))
- Accessibility: API/client accessibility; evidence REST/GraphQL errors; score 4/5 FAIL; Improvement: complete contract/CI evidence.
- Accountability: auditability of automated gate/backfill; evidence report writer; score 3/5 FAIL; Improvement: provide manual artifact.
- Accuracy: normalized email correctness; evidence normalizer/repository; score 4/5 FAIL; Improvement: complete CI.
- Adaptability: legacy/current email support; evidence fallback queries; score 4/5 FAIL; Improvement: complete CI.
- Administrability: operator backfill; evidence runbook/command; score 3/5 FAIL; Improvement: attach dry-run report.
- Affordability: bounded resource/cost impact; evidence batching/index; score 3/5 FAIL; Improvement: finish load/cache checks.
- Agility: CQRS separation; evidence changed command/handler; score 4/5 FAIL; Improvement: resolve review threads.
- Analyzability: tests/docs/graph evidence; score 4/5 FAIL; Improvement: close qlty findings.
- Auditability: JSON report and GitHub status; score 3/5 FAIL; Improvement: provide immutable report evidence.
- Autonomy: automated review loop; score 2/5 FAIL; Improvement: run/pass `make ai-review-loop`.
- Availability: safe failure paths; score 3/5 FAIL; Improvement: finish CI.
- Compatibility: REST/GraphQL/OpenAPI; score 4/5 FAIL; Improvement: finish Schemathesis/GraphQL checks.
- Composability: shared dispatcher/query handler; score 4/5 FAIL; Improvement: complete CI.
- Confidentiality: no token/cookie on ambiguity; score 4/5 FAIL; Improvement: finish security tests.
- Configurability: Mongo image env var; score 3/5 FAIL; Improvement: fix install/check workflow.
- Convenience: operator/API ergonomics; score 3/5 FAIL; Improvement: provide rollout evidence.
- Correctness: duplicate detection behavior; score 4/5 FAIL; Improvement: complete tests.
- Credibility: evidence trust; score 2/5 FAIL; Improvement: pass CI and PR review.
- Customizability: outside feature scope except config image; score 5/5 PASS; Improvement: none.
- Debuggability: JSON reports/tests; score 3/5 FAIL; Improvement: attach report and CI logs.
- Degradability: neutral password reset failure; score 4/5 FAIL; Improvement: complete CI.
- Determinability: deterministic normalization/backfill; score 3/5 FAIL; Improvement: pass automated checks.
- Demonstrability: tests present; score 3/5 FAIL; Improvement: get completed runs.
- Dependability: safe duplicate handling; score 3/5 FAIL; Improvement: pass full CI.
- Deployability: workflow failed; score 1/5 FAIL; Improvement: fix `symfony-checks`.
- Discoverability: docs/OpenAPI updated; score 4/5 FAIL; Improvement: finish spec checks.
- Distributability: no distributed topology change; graph shows no new queue edges; score 5/5 PASS; Improvement: none.
- Durability: Mongo persistence/index; score 3/5 FAIL; Improvement: pass DB integration tests.
- Effectiveness: user-registration outcome; score 4/5 FAIL; Improvement: complete CI.
- Efficiency: cache/index/batch; score 3/5 FAIL; Improvement: finish performance checks.
- Elasticity: no scaling topology change; load checks pending for changed cache/backfill; score 3/5 FAIL; Improvement: pass load checks.
- Evolvability: CQRS split; score 4/5 FAIL; Improvement: resolve review comments.
- Extensibility: shared services; score 4/5 FAIL; Improvement: complete CI.
- Failure Transparency: problem+json/neutral responses; score 4/5 FAIL; Improvement: finish integration checks.
- Familiarity: Symfony/API Platform patterns; score 4/5 FAIL; Improvement: resolve review threads.
- Fault-Tolerance: ambiguity abort/no mutation; score 4/5 FAIL; Improvement: finish CI.
- Fidelity: API behavior preserved; score 4/5 FAIL; Improvement: finish contract checks.
- Flexibility: DTO/dispatcher/repository support; score 4/5 FAIL; Improvement: complete CI.
- Inspectability: graph/tests/docs available; score 4/5 FAIL; Improvement: close PR review threads.
- Installability: CI install step failed; score 1/5 FAIL; Improvement: fix Symfony CLI install.
- Integrity: unique index/duplicate guard; score 4/5 FAIL; Improvement: pass DB tests.
- Interactivity: API-only interaction; score 4/5 FAIL; Improvement: finish REST/GraphQL checks.
- Interchangeability: no provider swap change; score 5/5 PASS; Improvement: none.
- Interoperability: OAuth/REST/GraphQL; score 3/5 FAIL; Improvement: complete contract CI.
- Intuitiveness: clear errors/docs; score 4/5 FAIL; Improvement: finish CI.
- Learnability: docs updated; score 4/5 FAIL; Improvement: add evidence artifact.
- Localizability: translation touched; score 4/5 FAIL; Improvement: pass tests.
- Maintainability: unresolved qlty threads; score 3/5 FAIL; Improvement: deduplicate/fix review comments.
- Manageability: backfill/runbook; score 3/5 FAIL; Improvement: attach dry-run JSON.
- Mobility: outside PR scope; no mobile surface changed; score 5/5 PASS; Improvement: none.
- Modifiability: CQRS refactor helps; score 4/5 FAIL; Improvement: close review threads.
- Modularity: shared dispatcher/query; score 4/5 FAIL; Improvement: complete CI.
- Observability: JSON report; score 3/5 FAIL; Improvement: provide artifact/log evidence.
- Operability: command/docs; score 3/5 FAIL; Improvement: manual rollout evidence.
- Orthogonality: domain/app separation; score 4/5 FAIL; Improvement: pass full architecture/CI gate.
- Portability: Docker image configurable; score 3/5 FAIL; Improvement: fix install check.
- Precision: exact/normalized lookup semantics; score 4/5 FAIL; Improvement: replace local normalizers.
- Predictability: deterministic duplicate behavior; score 4/5 FAIL; Improvement: pass CI.
- Process Capabilities: BMAD/make workflow; score 2/5 FAIL; Improvement: run required loop.
- Producibility: build/CI reproduction; score 1/5 FAIL; Improvement: fix failed workflow.
- Provability: evidence incomplete; score 2/5 FAIL; Improvement: finish checks.
- Recoverability: rollback/runbook; score 3/5 FAIL; Improvement: manual evidence.
- Redundancy: no redundancy surface changed; graph shows no HA topology change; score 5/5 PASS; Improvement: none.
- Relevance: implemented matches PRD; score 4/5 FAIL; Improvement: complete verification.
- Reliability: safe guards; score 3/5 FAIL; Improvement: pass tests.
- Repairability: docs/tests aid repair; score 3/5 FAIL; Improvement: close qlty issues.
- Repeatability: automated tests exist; score 2/5 FAIL; Improvement: pass CI.
- Reproducibility: CI failed/pending; score 1/5 FAIL; Improvement: fix and rerun.
- Resilience: ambiguity safe failures; score 4/5 FAIL; Improvement: finish CI.
- Responsiveness: load checks pending; score 3/5 FAIL; Improvement: pass load/cache checks.
- Reusability: shared dispatcher/normalizer; score 4/5 FAIL; Improvement: use shared normalizer everywhere.
- Robustness: negative tests exist; score 4/5 FAIL; Improvement: complete CI.
- Safety: no harmful account-link/token mutation; score 4/5 FAIL; Improvement: finish CI.
- Scalability: indexes/batching; score 3/5 FAIL; Improvement: pass load tests.
- Seamlessness: public behavior preserved in code; score 4/5 FAIL; Improvement: pass contract tests.
- Self-Sustainability: resource growth bounded but unverified; score 3/5 FAIL; Improvement: performance evidence.
- Serviceability: runbook/report; score 3/5 FAIL; Improvement: attach evidence.
- Securability: security controls present; score 4/5 FAIL; Improvement: pass security-relevant tests.
- Simplicity: CQRS cleanup; score 4/5 FAIL; Improvement: resolve duplicate-code reviews.
- Stability: CI not stable/passing; score 1/5 FAIL; Improvement: rerun to green.
- Standards Compliance: OpenAPI/API Platform; score 4/5 FAIL; Improvement: finish spec checks.
- Survivability: safe failure/rollback; score 3/5 FAIL; Improvement: manual rollback evidence.
- Sustainability: bounded cache/index/backfill; score 3/5 FAIL; Improvement: load/resource evidence.
- Tailorability: outside current feature except config image; score 5/5 PASS; Improvement: none.
- Testability: tests added; score 3/5 FAIL; Improvement: pass CI and resolve qlty.

[truncated after 160 lines]
Verification Output

Running on PHP 8.4.5, Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac.

JIT acceleration: OFF
You can enable JIT acceleration (experimental) with --force-jit.

Target PHP version: 8.4 (inferred from composer.json) Enabled extensions: dom, mongodb, simplexml.


Scanning files...


1 / 236...
10 / 236...
20 / 236...
30 / 236...
40 / 236...
50 / 236...
60 / 236...
70 / 236...
80 / 236...
90 / 236...
100 / 236...
110 / 236...
120 / 236...
130 / 236...
140 / 236...
150 / 236...
160 / 236...
170 / 236...
180 / 236...
190 / 236...
200 / 236...
210 / 236...
220 / 236...
230 / 236...
236 / 236...
240 / 301...
250 / 301...
260 / 301...
270 / 301...
280 / 301...
290 / 301...
300 / 301...
301 / 301...
310 / 633...
320 / 633...
330 / 633...
340 / 633...
350 / 633...
360 / 633...
370 / 633...
380 / 633...
390 / 633...
400 / 633...
410 / 633...
420 / 633...
430 / 633...
440 / 633...
450 / 633...
460 / 633...
470 / 633...
480 / 633...
490 / 633...
500 / 633...
510 / 633...
520 / 633...
530 / 633...
540 / 633...
550 / 633...
560 / 633...
570 / 633...
580 / 633...
590 / 633...
600 / 633...
610 / 633...
620 / 633...
630 / 633...
633 / 633...
640 / 805...
650 / 805...
660 / 805...
670 / 805...
680 / 805...
690 / 805...
700 / 805...
710 / 805...
720 / 805...
730 / 805...
740 / 805...
750 / 805...
760 / 805...
770 / 805...
780 / 805...
790 / 805...
800 / 805...
805 / 805...
810 / 872...
820 / 872...
830 / 872...
840 / 872...
850 / 872...
860 / 872...
870 / 872...
872 / 872...
880 / 902...
890 / 902...
900 / 902...
902 / 902...
910 / 920...
920 / 920...
930 / 953...
940 / 953...
950 / 953...
953 / 953...
956 / 956...
958 / 958...
960 / 2432...
970 / 2432...
980 / 2432...
990 / 2432...
1000 / 2432...
1010 / 2432...
1020 / 2432...
1030 / 2432...
1040 / 2432...
1050 / 2432...
1060 / 2432...
1070 / 2432...
1080 / 2432...
1090 / 2432...
1100 / 2432...
1110 / 2432...
1120 / 2432...
1130 / 2432...
1140 / 2432...
1150 / 2432...
1160 / 2432...
1170 / 2432...
1180 / 2432...
1190 / 2432...
1200 / 2432...
1210 / 2432...
1220 / 2432...
1230 / 2432...
1240 / 2432...
1250 / 2432...
1260 / 2432...
1270 / 2432...
1280 / 2432...
1290 / 2432...
1300 / 2432...
1310 / 2432...
1320 / 2432...
1330 / 2432...
1340 / 2432...
1350 / 2432...
1360 / 2432...
1370 / 2432...
1380 / 2432...
1390 / 2432...
1400 / 2432...
1410 / 2432...
1420 / 2432...
1430 / 2432...
1440 / 2432...
1450 / 2432...
1460 / 2432...
1470 / 2432...
1480 / 2432...
1490 / 2432...
1500 / 2432...
1510 / 2432...
1520 / 2432...
1530 / 2432...
1540 / 2432...
1550 / 2432...
1560 / 2432...
1570 / 2432...
1580 / 2432...
1590 / 2432...
1600 / 2432...
1610 / 2432...
1620 / 2432...
1630 / 2432...
1640 / 2432...
1650 / 2432...
1660 / 2432...
1670 / 2432...
1680 / 2432...
1690 / 2432...
1700 / 2432...
1710 / 2432...
1720 / 2432...
1730 / 2432...
1740 / 2432...
1750 / 2432...
1760 / 2432...
1770 / 2432...
1780 / 2432...
1790 / 2432...
1800 / 2432...
1810 / 2432...
1820 / 2432...
1830 / 2432...
1840 / 2432...
1850 / 2432...
1860 / 2432...
1870 / 2432...
1880 / 2432...
1890 / 2432...
1900 / 2432...
1910 / 2432...
1920 / 2432...
1930 / 2432...
1940 / 2432...
1950 / 2432...
1960 / 2432...
1970 / 2432...
1980 / 2432...
1990 / 2432...
2000 / 2432...
2010 / 2432...
2020 / 2432...
2030 / 2432...
2040 / 2432...
2050 / 2432...
2060 / 2432...
2070 / 2432...
2080 / 2432...
2090 / 2432...
2100 / 2432...
2110 / 2432...
2120 / 2432...
2130 / 2432...
2140 / 2432...
2150 / 2432...
2160 / 2432...
2170 / 2432...
2180 / 2432...
2190 / 2432...
2200 / 2432...
2210 / 2432...
2220 / 2432...
2230 / 2432...
2240 / 2432...
2250 / 2432...
2260 / 2432...
2270 / 2432...
2280 / 2432...
2290 / 2432...
2300 / 2432...
2310 / 2432...
2320 / 2432...
2330 / 2432...
2340 / 2432...
2350 / 2432...
2360 / 2432...
2370 / 2432...
2380 / 2432...
2390 / 2432...
2400 / 2432...
2410 / 2432...
2420 / 2432...
2430 / 2432...
2432 / 2432...
2433 / 2433...
2440 / 2696...
2450 / 2696...
2460 / 2696...
2470 / 2696...
2480 / 2696...
2490 / 2696...
2500 / 2696...
2510 / 2696...
2520 / 2696...
2530 / 2696...
2540 / 2696...
2550 / 2696...
2560 / 2696...
2570 / 2696...
2580 / 2696...
2590 / 2696...
2600 / 2696...
2610 / 2696...
2620 / 2696...
2630 / 2696...
2640 / 2696...
2650 / 2696...
2660 / 2696...
2670 / 2696...
2680 / 2696...
2690 / 2696...
2696 / 2696...
2700 / 3210...
2710 / 3210...
2720 / 3210...
2730 / 3210...
2740 / 3210...
2750 / 3210...
2760 / 3210...
2770 / 3210...
2780 / 3210...
2790 / 3210...
2800 / 3210...
2810 / 3210...
2820 / 3210...
2830 / 3210...
2840 / 3210...
2850 / 3210...
2860 / 3210...
2870 / 3210...
2880 / 3210...
2890 / 3210...
2900 / 3210...
2910 / 3210...
2920 / 3210...
2930 / 3210...
2940 / 3210...
2950 / 3210...
2960 / 3210...
2970 / 3210...
2980 / 3210...
2990 / 3210...
3000 / 3210...
3010 / 3210...
3020 / 3210...
3030 / 3210...
3040 / 3210...
3050 / 3210...
3060 / 3210...
3070 / 3210...
3080 / 3210...
3090 / 3210...
3100 / 3210...
3110 / 3210...
3120 / 3210...
3130 / 3210...
3140 / 3210...
3150 / 3210...
3160 / 3210...
3170 / 3210...
3180 / 3210...
3190 / 3210...
3200 / 3210...
3210 / 3210...
3220 / 3752...
3230 / 3752...
3240 / 3752...
3250 / 3752...
3260 / 3752...
3270 / 3752...
3280 / 3752...
3290 / 3752...
3300 / 3752...
3310 / 3752...
3320 / 3752...
3330 / 3752...
3340 / 3752...
3350 / 3752...
3360 / 3752...
3370 / 3752...
3380 / 3752...
3390 / 3752...
3400 / 3752...
3410 / 3752...
3420 / 3752...
3430 / 3752...
3440 / 3752...
3450 / 3752...
3460 / 3752...
3470 / 3752...
3480 / 3752...
3490 / 3752...
3500 / 3752...
3510 / 3752...
3520 / 3752...
3530 / 3752...
3540 / 3752...
3550 / 3752...
3560 / 3752...
3570 / 3752...
3580 / 3752...
3590 / 3752...
3600 / 3752...
3610 / 3752...
3620 / 3752...
3630 / 3752...
3640 / 3752...
3650 / 3752...
3660 / 3752...
3670 / 3752...
3680 / 3752...
3690 / 3752...
3700 / 3752...
3710 / 3752...
3720 / 3752...
3730 / 3752...
3740 / 3752...
3750 / 3752...
3752 / 3752...
3760 / 4159...
3770 / 4159...
3780 / 4159...
3790 / 4159...
3800 / 4159...
3810 / 4159...
3820 / 4159...
3830 / 4159...
3840 / 4159...
3850 / 4159...
3860 / 4159...
3870 / 4159...
3880 / 4159...
3890 / 4159...
3900 / 4159...
3910 / 4159...
3920 / 4159...
3930 / 4159...
3940 / 4159...
3950 / 4159...
3960 / 4159...
3970 / 4159...
3980 / 4159...
3990 / 4159...
4000 / 4159...
4010 / 4159...
4020 / 4159...
4030 / 4159...
4040 / 4159...
4050 / 4159...
4060 / 4159...
4070 / 4159...
4080 / 4159...
4090 / 4159...
4100 / 4159...
4110 / 4159...
4120 / 4159...
4130 / 4159...
4140 / 4159...
4150 / 4159...
4159 / 4159...
4160 / 4416...
4170 / 4416...
4180 / 4416...
4190 / 4416...
4200 / 4416...
4210 / 4416...
4220 / 4416...
4230 / 4416...
4240 / 4416...
4250 / 4416...
4260 / 4416...
4270 / 4416...
4280 / 4416...
4290 / 4416...
4300 / 4416...
4310 / 4416...
4320 / 4416...
4330 / 4416...
4340 / 4416...
4350 / 4416...
4360 / 4416...
4370 / 4416...
4380 / 4416...
4390 / 4416...
4400 / 4416...
4410 / 4416...
4416 / 4416...
4420 / 4543...
4430 / 4543...
4440 / 4543...
4450 / 4543...
4460 / 4543...
4470 / 4543...
4480 / 4543...
4490 / 4543...
4500 / 4543...
4510 / 4543...
4520 / 4543...
4530 / 4543...
4540 / 4543...
4543 / 4543...
4550 / 4587...
4560 / 4587...
4570 / 4587...
4580 / 4587...
4587 / 4587...
4590 / 4598...
4598 / 4598...
4600 / 4615...
4610 / 4615...
4615 / 4615...

Analyzing files...

░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   60 / 1474 (4%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  120 / 1474 (8%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  180 / 1474 (12%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  240 / 1474 (16%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  300 / 1474 (20%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  360 / 1474 (24%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  420 / 1474 (28%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  480 / 1474 (32%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  540 / 1474 (36%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  600 / 1474 (40%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  660 / 1474 (44%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  720 / 1474 (48%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  780 / 1474 (52%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  840 / 1474 (56%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  900 / 1474 (61%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  960 / 1474 (65%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1020 / 1474 (69%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1080 / 1474 (73%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1140 / 1474 (77%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1200 / 1474 (81%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1260 / 1474 (85%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1320 / 1474 (89%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1380 / 1474 (93%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1440 / 1474 (97%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

------------------------------
�[42;2m                              �[0m
�[42;30;2m       No errors found!       �[0m
�[42;2m                              �[0m
------------------------------
2664 other issues found.
You can display them with �[30;48;5;195m--show-info=true�[0m
------------------------------
Psalm can automatically fix 50 of these issues.
Run Psalm again with 
�[30;48;5;195m--alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockReturnType,MissingClosureReturnType,MissingParamType,ClassMustBeFinal --dry-run�[0m
to see what it can fix.
------------------------------

Checks took 43.31 seconds and used 1,058.622MB of memory
Psalm was able to infer types for 97.8055% of the codebase

Comment thread src/User/Application/Validator/UserCredentialValidator.php
Comment thread src/User/Infrastructure/Repository/CachedUserRepository.php
Signed-off-by: Vadym <kostiukdsfv@gmail.com>
Comment thread src/User/Application/Validator/UserCredentialValidator.php
Comment thread src/User/Infrastructure/Repository/CachedUserRepository.php
Comment thread src/User/Application/Validator/UserCredentialValidator.php
Comment thread src/User/Infrastructure/Repository/CachedUserRepository.php
Comment thread src/User/Application/Validator/UserCredentialValidator.php
Comment thread src/User/Infrastructure/Repository/CachedUserRepository.php
Comment thread src/User/Application/Validator/UserCredentialValidator.php
Comment thread src/User/Infrastructure/Repository/CachedUserRepository.php
Comment thread src/User/Application/Validator/UserCredentialValidator.php
Comment thread src/User/Infrastructure/Repository/CachedUserRepository.php
Comment thread src/User/Application/Validator/UserCredentialValidator.php
Comment thread src/User/Infrastructure/Repository/CachedUserRepository.php
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor: RegisterUserCommandHandler to Remove Side Effects and Follow CQRS Pattern

3 participants