Skip to content

chore(release): Prepare v2.2.0 - #41

Merged
soulevilx merged 4 commits into
masterfrom
release/2.2.0
Aug 2, 2026
Merged

chore(release): Prepare v2.2.0#41
soulevilx merged 4 commits into
masterfrom
release/2.2.0

Conversation

@soulevilx

Copy link
Copy Markdown
Contributor

Summary

Release flow next steps

  1. Merge this PR into master
  2. Tag v2.2.0 from master (triggers release workflow + Packagist)
  3. Merge master back into develop

Test plan

  • composer check
  • composer ci
  • CI green on this release PR
  • After merge: create/push tag v2.2.0
  • Validate GitHub Release + Packagist

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b42f1b6f-7e0a-4370-880c-760f10b1a1da

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

chore(release): Prepare v2.2.0 (security hardening, resilience, docs)

✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Prepare v2.2.0 release with finalized changelog and MIT license.
• Harden CI/security (SHA-pinned actions, checksum Gitleaks, dependency review notes).
• Improve client resilience, logging sanitization, and exception hierarchy; add coverage via tests.
Diagram

graph TD
  A["ClientBuilder"] --> B["Middleware pipeline"] --> C["HttpClient"] --> D["Guzzle adapter"] --> E["Guzzle"]
  B --> F["LogSanitizer"]
  B --> G["StateStore"]
  C --> H["JOO exceptions"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Introduce a capability interface for half-open probe claiming
  • ➕ Avoids breaking custom StateStoreInterface implementors by not adding a required method
  • ➕ Allows different stores to opt into single-flight behavior (atomic stores) while keeping best-effort stores simpler
  • ➖ More types/complexity (extra interface + branching in CircuitBreakerMiddleware)
  • ➖ Requires a migration path and documentation for store authors
2. Provide a built-in atomic store (e.g., Redis) for cross-process single-flight probes
  • ➕ Makes tryClaimProbe semantics correct under concurrency (cluster-safe)
  • ➕ Reduces user burden for production deployments requiring strict guarantees
  • ➖ Adds an external dependency and operational overhead
  • ➖ Expands maintenance surface area (drivers, connection handling, failure modes)

Recommendation: The overall approach is sound (security hardening + ecosystem-aligned exception bases + better resilience and sanitization). The main strategic concern is the API impact of adding tryClaimProbe() to StateStoreInterface (a breaking change for custom stores). If BC is a priority for 2.x minors, prefer a capability interface (or a new v2 interface) and conditionally enforce single-flight only when supported; otherwise, proceed as-is but call out the required store update in upgrade notes/release notes.

Files changed (67) +1149 / -325

Enhancement (9) +117 / -15
ClientBuilder.phpDeprecate request coalescing builder hook and fix production middleware order +7/-0

Deprecate request coalescing builder hook and fix production middleware order

• Marks request coalescing as deprecated due to sync/async limitations. Ensures correlation ID middleware is registered before logging so log context is populated.

src/Client/ClientBuilder.php

ClientException.phpRebase ClientException on shared JOO runtime exception base +2/-2

Rebase ClientException on shared JOO runtime exception base

• Changes ClientException to extend AbstractJOORuntimeException from jooservices/exceptions to enforce ecosystem-wide exception contracts.

src/Exceptions/ClientException.php

InvalidConfigurationException.phpRebase InvalidConfigurationException on shared JOO logic exception base +2/-2

Rebase InvalidConfigurationException on shared JOO logic exception base

• Moves InvalidConfigurationException from InvalidArgumentException to AbstractJOOLogicException, aligning configuration errors with a logic exception hierarchy.

src/Exceptions/InvalidConfigurationException.php

LogSanitizer.phpExpand redaction set and sanitize exception messages with truncation +44/-3

Expand redaction set and sanitize exception messages with truncation

• Exposes default sensitive header/query lists and adds defaultRedactKeys() for structured loggers. Introduces sanitizeExceptionMessage() to redact URIs inside exception text and cap message length.

src/Logging/LogSanitizer.php

CircuitBreakerMiddleware.phpAdd half-open single-flight probe claiming +5/-0

Add half-open single-flight probe claiming

• When half-open, enforces a single in-flight probe by calling StateStoreInterface::tryClaimProbe(), rejecting concurrent probes with CircuitOpenException.

src/Middleware/CircuitBreakerMiddleware.php

RetryMiddleware.phpSkip jitter when delay is sourced from Retry-After +8/-5

Skip jitter when delay is sourced from Retry-After

• Changes delay resolution to return (delay, fromRetryAfter) and disables jitter randomization when respecting server-provided Retry-After values.

src/Middleware/RetryMiddleware.php

StateStoreInterface.phpAdd tryClaimProbe() for half-open single-flight probing +7/-0

Add tryClaimProbe() for half-open single-flight probing

• Extends the circuit breaker state store contract with an atomic-ish probe claim method to prevent overlapping half-open probes.

src/Resilience/Contracts/StateStoreInterface.php

InMemoryStateStore.phpImplement probe-in-flight tracking for half-open probing +15/-0

Implement probe-in-flight tracking for half-open probing

• Adds probeInFlight state and implements tryClaimProbe() with release-on-success/failure/reset semantics to enforce single-flight behavior in-process.

src/Resilience/Storage/InMemoryStateStore.php

Psr16StateStore.phpAdd probe claim support and document PSR-16 concurrency limitations +27/-3

Add probe claim support and document PSR-16 concurrency limitations

• Adds probeInFlight to cached state and implements tryClaimProbe() while explicitly documenting the non-atomic nature and race risks under multi-worker concurrency.

src/Resilience/Storage/Psr16StateStore.php

Bug fix (8) +82 / -29
GuzzleHttpClientAdapter.phpImprove connect-timeout detection across Guzzle 7/8 +23/-2

Improve connect-timeout detection across Guzzle 7/8

• Refactors connect exception handling into a helper that prefers typed Guzzle 8 ConnectTimeoutException, then cURL errno=28 from handler context, and finally message matching.

src/Adapters/Guzzle/GuzzleHttpClientAdapter.php

MongoDbLogger.phpDefault MongoDbLogger redact keys to LogSanitizer::defaultRedactKeys() +4/-3

Default MongoDbLogger redact keys to LogSanitizer::defaultRedactKeys()

• Allows redactKeys to be null and defaults to LogSanitizer-provided keys, aligning Mongo logging redaction behavior with core sanitization rules.

src/Logging/MongoDbLogger.php

MonologFactory.phpHarden log directory domain sanitization against path traversal +6/-2

Harden log directory domain sanitization against path traversal

• Rejects '..' and empty domain outcomes after sanitization to prevent writing logs outside intended directories, defaulting to 'unknown' when needed.

src/Logging/MonologFactory.php

DeadlineMiddleware.phpPreserve sub-second deadlines with float timeouts +5/-5

Preserve sub-second deadlines with float timeouts

• Changes deadline conversion to use fractional seconds and preserves float connect_timeout handling, improving precision for small deadlines.

src/Middleware/DeadlineMiddleware.php

LoggingMiddleware.phpSanitize exception messages and bound body logging reads +20/-12

Sanitize exception messages and bound body logging reads

• Redacts sensitive URIs embedded in exception messages before logging. Reworks body logging to read only a bounded prefix from seekable streams and avoids reading full payloads into memory.

src/Middleware/LoggingMiddleware.php

OAuthTokenRefreshMiddleware.phpRewind request bodies before retrying after token refresh +5/-0

Rewind request bodies before retrying after token refresh

• Ensures seekable request bodies are rewound before resending requests during refresh flows, preventing empty-body retries for buffered streams.

src/Middleware/OAuthTokenRefreshMiddleware.php

HmacSha256Signer.phpRewind seekable request bodies after signing +6/-1

Rewind seekable request bodies after signing

• Reads the body for signing and rewinds seekable streams to avoid consuming the body before the request is sent.

src/Signing/HmacSha256Signer.php

W3cTraceContextGenerator.phpTighten traceparent validation to lowercase and non-zero IDs +13/-4

Tighten traceparent validation to lowercase and non-zero IDs

• Enforces lowercase hex per spec and rejects all-zero trace-id/parent-id values, improving correctness and preventing invalid propagation.

src/Support/W3cTraceContextGenerator.php

Refactor (1) +0 / -3
HttpClient.phpSimplify batch error callback handling +0/-3

Simplify batch error callback handling

• Removes an unused rejection callback argument in the batch settlement logic, reducing noise and aligning with result storage behavior.

src/Client/HttpClient.php

Tests (15) +464 / -50
ArchitectureTest.phpAdd architecture tests for namespace, adapter isolation, and exception inheritance +177/-0

Add architecture tests for namespace, adapter isolation, and exception inheritance

• Introduces a PHPUnit arch suite ensuring src namespaces are correct, Guzzle exceptions stay confined to adapters/testing, Laravel imports are absent, and package exceptions conform to the shared JOO exception contracts.

tests/Arch/ArchitectureTest.php

TestCase.phpEnable Mockery expectation verification via MockeryPHPUnitIntegration +3/-0

Enable Mockery expectation verification via MockeryPHPUnitIntegration

• Adds the MockeryPHPUnitIntegration trait so Mockery expectations like once()/never() are asserted during PHPUnit teardown.

tests/TestCase.php

GuzzleHttpClientAdapterTest.phpExpand timeout detection tests for Guzzle 7/8 variants +57/-1

Expand timeout detection tests for Guzzle 7/8 variants

• Adds coverage for typed connect-timeout exceptions and handler-context errno-based detection, plus a separate message-based fallback test.

tests/Unit/Adapters/GuzzleHttpClientAdapterTest.php

ClientBuilderTest.phpUpdate logging expectations and WAN IP provider return-type correctness +6/-8

Update logging expectations and WAN IP provider return-type correctness

• Adjusts expected log call counts and tweaks anonymous WAN IP provider implementations to satisfy static analysis and expectation enforcement.

tests/Unit/Client/ClientBuilderTest.php

HttpClientDownloadTest.phpAlign download logging expectations with info-level logging behavior +1/-2

Align download logging expectations with info-level logging behavior

• Updates Mockery expectations to match the middleware’s info-level calls (and removes outdated log()-level expectations).

tests/Unit/Client/HttpClientDownloadTest.php

LogSanitizerTest.phpAdd coverage for expanded redaction and exception message sanitization +25/-1

Add coverage for expanded redaction and exception message sanitization

• Extends query param redaction assertions to include refresh_token/client_secret/id_token/code and adds tests for sanitizeExceptionMessage() redaction and truncation behavior.

tests/Unit/Logging/LogSanitizerTest.php

MonologFactoryTest.phpTest domain path traversal rejection +25/-0

Test domain path traversal rejection

• Adds a test ensuring MonologFactory sanitizes '..' domains into a safe directory and does not write outside the expected base path.

tests/Unit/Logging/MonologFactoryTest.php

CircuitBreakerMiddlewareTest.phpAdd half-open single-flight probe tests +51/-0

Add half-open single-flight probe tests

• Adds tests validating only one half-open probe can be claimed at a time and that the claim is released after successful probes and recovery.

tests/Unit/Middleware/CircuitBreakerMiddlewareTest.php

ExtendedMiddlewareTest.phpAdd W3C traceparent negative cases and deadline precision assertions +27/-1

Add W3C traceparent negative cases and deadline precision assertions

• Expands traceparent validation tests for uppercase and all-zero IDs and adds deadline middleware assertions to confirm sub-second timeout precision and connect_timeout behavior.

tests/Unit/Middleware/ExtendedMiddlewareTest.php

LoggingMiddlewareTest.phpUpdate logging middleware tests for info/error calls and PSR-3 signatures +29/-32

Update logging middleware tests for info/error calls and PSR-3 signatures

• Adjusts expectations to match direct info()/error() usage, updates debug-body behavior expectations, and fixes a test logger’s PSR-3 method signatures to use string|Stringable.

tests/Unit/Middleware/LoggingMiddlewareTest.php

RetryMiddlewareTest.phpAdd test ensuring jitter is skipped for Retry-After delays +35/-0

Add test ensuring jitter is skipped for Retry-After delays

• Introduces a deterministic test confirming that when Retry-After is present, the middleware sleeps exactly that duration without jitter randomization.

tests/Unit/Middleware/RetryMiddlewareTest.php

InMemoryStateStoreTest.phpAdd tests for tryClaimProbe() semantics +14/-0

Add tests for tryClaimProbe() semantics

• Adds unit tests confirming only one probe can be claimed at a time and that success/failure resets allow future probe claims.

tests/Unit/Resilience/InMemoryStateStoreTest.php

Psr16StateStoreTest.phpAdd tests for PSR-16 store probe claiming behavior +11/-0

Add tests for PSR-16 store probe claiming behavior

• Adds unit tests validating tryClaimProbe() and release behavior after successful half-open reporting in the PSR-16 backed implementation.

tests/Unit/Resilience/Psr16StateStoreTest.php

FinalCoverageTest.phpUpdate coverage test expectations for logging middleware +0/-1

Update coverage test expectations for logging middleware

• Removes outdated expectations around logger->log() to match the middleware’s direct method calls.

tests/Unit/Support/FinalCoverageTest.php

RemainingCoverageTest.phpRefine non-seekable body logging expectations +3/-4

Refine non-seekable body logging expectations

• Updates tests to assert request body debug is skipped while response body debug behavior matches the bounded seekable-read implementation.

tests/Unit/Support/RemainingCoverageTest.php

Documentation (25) +281 / -127
AGENTS.mdDocument ecosystem exception base requirement and resilience store semantics +3/-1

Document ecosystem exception base requirement and resilience store semantics

• Adds rules about package exceptions inheriting from jooservices/exceptions bases and clarifies in-memory vs PSR-16 store guarantees/limitations for resilience features.

AGENTS.md

CHANGELOG.mdAdd v2.2.0 release notes (2026-08-02) +37/-0

Add v2.2.0 release notes (2026-08-02)

• Introduces a comprehensive 2.2.0 section covering added features, behavioral changes, fixes, deprecations, and removals.

CHANGELOG.md

LICENSEAdd MIT license file +21/-0

Add MIT license file

• Adds an MIT LICENSE file for distribution and compliance clarity.

LICENSE

README.mdDocument runtime dependency set including jooservices/exceptions +2/-0

Document runtime dependency set including jooservices/exceptions

• Adds a short note listing the primary runtime dependencies, including the new jooservices/exceptions requirement.

README.md

UPGRADE-2.0.mdCall out InvalidConfigurationException base-class change +1/-0

Call out InvalidConfigurationException base-class change

• Updates the upgrade guide to note that InvalidConfigurationException no longer extends InvalidArgumentException and instead inherits from the shared JOO logic exception base.

UPGRADE-2.0.md

01-project-overview.mdUpdate release target and align git-hook documentation +4/-5

Update release target and align git-hook documentation

• Bumps documented release target to 2.2.0 and updates development scripts guidance to reflect CaptainHook-managed hooks instead of a scripts/git-hooks pre-commit file.

docs/00-architecture/01-project-overview.md

02-repository-structure.mdRemove stale config/ directory mention +0/-1

Remove stale config/ directory mention

• Updates repository structure docs to remove the config/ directory entry after cleanup of unused runtime config assets.

docs/00-architecture/02-repository-structure.md

04-modules-and-domains.mdCorrect ‘not implemented’ list to reflect shipped features +2/-7

Correct ‘not implemented’ list to reflect shipped features

• Adjusts documentation that previously listed several now-implemented features (rate limiting, signing, OAuth refresh, metrics, trace context, etc.) as missing.

docs/00-architecture/04-modules-and-domains.md

05-data-flow.mdClarify circuit breaker store behavior and PSR-16 non-atomicity +5/-4

Clarify circuit breaker store behavior and PSR-16 non-atomicity

• Documents that InMemory stores are process-local and that PSR-16 stores are best-effort due to non-atomic read-modify-write behavior, with recommendations for atomic backends.

docs/00-architecture/05-data-flow.md

basic-concepts.mdUpdate release target and remove Laravel coupling references +5/-4

Update release target and remove Laravel coupling references

• Updates the stated release target to 2.2.0 and clarifies the package is framework-agnostic with native mongodb/mongodb usage and shared exception bases.

docs/01-getting-started/basic-concepts.md

installation.mdAlign CLI commands and document shipped Docker toolchain +11/-20

Align CLI commands and document shipped Docker toolchain

• Fixes benchmark command to composer bench and replaces speculative Docker recommendations with the repository’s actual Dockerfile/docker-compose instructions.

docs/01-getting-started/installation.md

api-reference.mdUpdate API docs for config defaults, MongoDbLogger factories, and exception bases +25/-19

Update API docs for config defaults, MongoDbLogger factories, and exception bases

• Refreshes API reference to match current defaults (connectTimeout/httpErrors), documents MongoDbLogger factory usage, and updates exception inheritance notes to reflect jooservices/exceptions bases.

docs/02-user-guide/api-reference.md

01-basic-get.phpModernize basic GET example with package exceptions and safer JSON handling +13/-9

Modernize basic GET example with package exceptions and safer JSON handling

• Switches to package exception types (and JOOExceptionInterface), uses ResponseWrapper helpers like successful(), and hardens JSON field extraction for PHPStan cleanliness.

docs/03-examples/01-basic-get.php

02-post-with-json.phpAdd error handling and safer output for POST JSON example +22/-16

Add error handling and safer output for POST JSON example

• Wraps the request in try/catch, uses successful(), ensures scalar ID formatting, and switches to response->body() for output consistency.

docs/03-examples/02-post-with-json.php

03-async-requests.phpType async unwrap results and handle client exceptions +24/-20

Type async unwrap results and handle client exceptions

• Uses Guzzle Promise Utils directly, annotates result types for static analysis, and ensures safe title extraction with a client-exception catch.

docs/03-examples/03-async-requests.php

04-error-handling.phpUpdate error handling example to library exception taxonomy +14/-7

Update error handling example to library exception taxonomy

• Replaces Guzzle exception usage with package exceptions (TimeoutException, NetworkConnectionException, HttpResponseException) and demonstrates enabling httpErrors for 4xx/5xx throwing.

docs/03-examples/04-error-handling.php

05-middleware-logging.phpMake logging example robust to failures and file read errors +10/-3

Make logging example robust to failures and file read errors

• Adds ClientException handling around the request and guards reading the log file. Minor string formatting cleanup for examples gating.

docs/03-examples/05-middleware-logging.php

06-production-middleware.phpHarden production middleware example for PHPStan and runtime errors +10/-3

Harden production middleware example for PHPStan and runtime errors

• Wraps the request with ClientException handling, uses uniqid with more entropy, and safely extracts JSON fields to keep examples runnable and analyzable.

docs/03-examples/06-production-middleware.php

ci-cd.mdDocument CI job inventory, SHA pinning, and required check contexts +12/-5

Document CI job inventory, SHA pinning, and required check contexts

• Updates workflow descriptions (including Guzzle 7 compat and hardened Gitleaks), clarifies dependency-review non-blocking behavior, and links to required status checks documentation.

docs/04-development/ci-cd.md

linting-standards.mdAdd PHPStan examples gate and enforce green examples policy +4/-1

Add PHPStan examples gate and enforce green examples policy

• Documents phpstan-examples.neon and updates lint:phpstan behavior to run three configs. Adds guidance to avoid ignoreErrors and prefer package exceptions in examples.

docs/04-development/linting-standards.md

secret-scanning.mdDocument Gitleaks configuration and CI hardening strategy +13/-2

Document Gitleaks configuration and CI hardening strategy

• Explains the base rules extension, checksum-verified binary install, base-SHA config loading on PRs, and placeholder allowlisting policy.

docs/04-development/secret-scanning.md

03-external-ci-integrations.mdAdd ruleset-required status checks and dependency graph guidance +31/-0

Add ruleset-required status checks and dependency graph guidance

• Documents which GitHub Actions contexts are required by the develop/master ruleset and clarifies which checks are optional/non-blocking, including dependency review prerequisites.

docs/05-maintenance/03-external-ci-integrations.md

README.mdLink to External CI Integrations doc +1/-0

Link to External CI Integrations doc

• Adds External CI Integrations to the maintenance documentation index.

docs/05-maintenance/README.md

RequestCoalescingMiddleware.phpDeprecate request coalescing middleware due to sync pipeline limitations +4/-0

Deprecate request coalescing middleware due to sync pipeline limitations

• Adds a deprecation notice explaining the lack of benefit outside a single-process synchronous path and recommends application-level deduplication instead.

src/Middleware/RequestCoalescingMiddleware.php

Psr16RateLimitStore.phpDocument PSR-16 rate limiter non-atomic read-modify-write behavior +7/-0

Document PSR-16 rate limiter non-atomic read-modify-write behavior

• Adds a warning docblock explaining that PSR-16 is best-effort under concurrency and recommends CAS/locking stores for strict limits.

src/Resilience/Storage/Psr16RateLimitStore.php

Other (9) +205 / -101
.gitattributesFix export-ignore entries for Pint and PHPStan test configs +3/-1

Fix export-ignore entries for Pint and PHPStan test configs

• Adds missing phpstan-tests config files to export-ignore and corrects the Pint config filename so release archives exclude the intended dev assets.

.gitattributes

ci.ymlPin CI actions by commit SHA and document dependency review behavior +24/-21

Pin CI actions by commit SHA and document dependency review behavior

• Replaces tag-based action references with commit-SHA pins for checkout/setup-php/composer-install/codecov/upload-artifact. Adds clarifying comments for dependency-review job requirements and keeps it non-blocking.

.github/workflows/ci.yml

scorecard.ymlPin Scorecard workflow actions by commit SHA +3/-3

Pin Scorecard workflow actions by commit SHA

• Pins checkout, scorecard-action, and upload-sarif actions to specific SHAs to improve supply-chain integrity and reproducibility.

.github/workflows/scorecard.yml

secret-scanning.ymlHarden secret scanning with checksum-verified Gitleaks CLI and base-SHA config +48/-13

Harden secret scanning with checksum-verified Gitleaks CLI and base-SHA config

• Adds scheduled and manual triggers, concurrency control, and narrows permissions. Installs Gitleaks via checksum verification and, for PRs, loads the config from the base branch SHA to prevent weakening rules in the PR.

.github/workflows/secret-scanning.yml

.gitleaks.tomlExtend default Gitleaks rules and expand allowlists/stopwords +40/-5

Extend default Gitleaks rules and expand allowlists/stopwords

• Switches to a documented config that extends the default ruleset (useDefault=true). Expands allowlisted paths and placeholder patterns so examples and fixtures don’t trigger false positives while still detecting real secrets.

.gitleaks.toml

composer.jsonAdd jooservices/exceptions dependency and PHPStan examples gate +3/-1

Add jooservices/exceptions dependency and PHPStan examples gate

• Adds jooservices/exceptions (^0.5) as a runtime requirement. Extends lint:phpstan to also analyze runnable examples via phpstan-examples.neon.

composer.json

composer.lockLock jooservices/exceptions v0.5.0 +58/-1

Lock jooservices/exceptions v0.5.0

• Updates the lockfile content hash and adds jooservices/exceptions v0.5.0 to the resolved dependency set.

composer.lock

phpstan-examples.neonAdd PHPStan config for runnable examples +6/-0

Add PHPStan config for runnable examples

• Introduces a max-level PHPStan configuration targeting docs/03-examples with strict unmatched-ignore reporting.

phpstan-examples.neon

phpstan-tests-baseline.neonUpdate PHPStan test baseline for shifted lines and new findings +20/-56

Update PHPStan test baseline for shifted lines and new findings

• Adjusts baseline entries after test changes (line offsets and new suppressed findings) to keep phpstan-tests gate stable.

phpstan-tests-baseline.neon

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.70330% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 98.82%. Comparing base (622e033) to head (bcba733).

Files with missing lines Patch % Lines
src/Logging/LogSanitizer.php 93.33% 1 Missing ⚠️
src/Logging/MonologFactory.php 75.00% 1 Missing ⚠️
src/Middleware/DeadlineMiddleware.php 80.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master      #41      +/-   ##
============================================
+ Coverage     98.72%   98.82%   +0.10%     
- Complexity      940      949       +9     
============================================
  Files            71       70       -1     
  Lines          2198     2219      +21     
============================================
+ Hits           2170     2193      +23     
+ Misses           28       26       -2     
Flag Coverage Δ
unittests 98.82% <96.70%> (+0.10%) ⬆️

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.

@soulevilx
soulevilx merged commit eb63263 into master Aug 2, 2026
16 checks passed
@soulevilx
soulevilx deleted the release/2.2.0 branch August 2, 2026 22:54
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. StateStoreInterface API break 🐞 Bug ⚙ Maintainability
Description
StateStoreInterface now requires tryClaimProbe(), which is a breaking change for any downstream
custom state-store implementations and can cause fatal interface-mismatch errors on upgrade. Docs
explicitly describe custom StateStoreInterface implementations as a supported scalability path,
but this release is targeting v2.2.0 (minor).
Code

src/Resilience/Contracts/StateStoreInterface.php[R19-21]

+     * @return bool true if this caller may send the probe; false if another probe is in flight
+     */
+    public function tryClaimProbe(): bool;
Evidence
The PR adds a new required method to a public interface, and repository docs describe implementing
that interface in custom backends; adding a required method is a BC break for implementers.

src/Resilience/Contracts/StateStoreInterface.php[7-26]
docs/00-architecture/05-data-flow.md[995-1003]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
A new required method (`tryClaimProbe()`) was added to the public `StateStoreInterface`, which breaks any consumer implementation of that interface.

### Issue Context
The docs encourage implementing custom `StateStoreInterface` backends for horizontal scaling, so this interface is part of the supported extension surface.

### Fix Focus Areas
- Revert the breaking interface change by removing `tryClaimProbe()` from `StateStoreInterface` and introducing an *optional* interface (e.g., `HalfOpenProbeStoreInterface`) that defines `tryClaimProbe()`.
- Update built-in stores (`InMemoryStateStore`, `Psr16StateStore`) to implement the optional interface.
- Update `CircuitBreakerMiddleware` to call `tryClaimProbe()` only when the resolved store implements the optional interface (or via `method_exists`), otherwise proceed without single-flight gating.

### Fix Focus Areas (code pointers)
- src/Resilience/Contracts/StateStoreInterface.php[7-26]
- src/Middleware/CircuitBreakerMiddleware.php[28-40]
- src/Resilience/Storage/InMemoryStateStore.php[9-93]
- src/Resilience/Storage/Psr16StateStore.php[17-118]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Probe claim lacks expiry 🐞 Bug ☼ Reliability
Description
Psr16StateStore::tryClaimProbe() persists a probeInFlight flag with no lease/expiry; if the
worker that claimed the probe crashes or is killed before reporting success/failure, subsequent
half-open attempts can be rejected indefinitely until cache eviction/manual reset.
CircuitBreakerMiddleware rejects requests when tryClaimProbe() fails and does so before entering
its try/catch, so callers don’t execute any automatic cleanup path.
Code

src/Resilience/Storage/Psr16StateStore.php[R109-112]

+        $state['probeInFlight'] = true;
+        $this->writeState($state);
+
+        return true;
Evidence
The middleware gates half-open execution on tryClaimProbe(), while the PSR-16 store sets
probeInFlight=true and writes state without any TTL/lease mechanism; if the claiming execution
never reaches success/failure reporting, the flag remains set.

src/Middleware/CircuitBreakerMiddleware.php[28-40]
src/Resilience/Storage/Psr16StateStore.php[102-144]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`probeInFlight` can become a stale lock in shared caches: it is written with no lease/expiry and is only cleared on success/failure paths that won’t run if the claiming process terminates.

### Issue Context
`CircuitBreakerMiddleware` blocks half-open calls when `tryClaimProbe()` returns false, which makes a stale `probeInFlight=true` effectively wedge the circuit-breaker in practice.

### Fix Focus Areas
- Store a `probeClaimedAt` timestamp alongside `probeInFlight`.
- In `tryClaimProbe()`, if `probeInFlight` is true but `probeClaimedAt` is older than a configured/max lease duration, clear it and allow a new claim.
- Introduce a configurable probe lease duration (e.g., on `CircuitBreakerConfig`) or derive a safe default (e.g., based on request timeout/deadline) so the stale-probe window is bounded.
- Ensure both `Psr16StateStore` and `InMemoryStateStore` follow the same stale-claim semantics.

### Fix Focus Areas (code pointers)
- src/Middleware/CircuitBreakerMiddleware.php[28-67]
- src/Resilience/Storage/Psr16StateStore.php[58-157]
- src/Resilience/Storage/InMemoryStateStore.php[11-93]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. README lists Guzzle ^7.10 📘 Rule violation ⚙ Maintainability
Description
The updated README states runtime support for Guzzle ^7.10 || ^8.0, which contradicts the
compliance requirement that 2.0+ documentation specify Guzzle ^8.0 as the dependency requirement.
This can mislead integrators about the required major version for 2.0+ usage and support
expectations.
Code

README.md[32]

+Runtime dependencies include Guzzle (`^7.10 || ^8.0`), `jooservices/exceptions` (`^0.5`), Monolog, and `mongodb/mongodb` (`^2.0`).
Evidence
PR Compliance ID 12 requires 2.0+ documentation to specify Guzzle ^8.0. The new README line
explicitly documents Guzzle as ^7.10 || ^8.0, which does not meet that requirement as written.

AGENTS.md: For 2.0+ Documentation, Specify Dependency and Integration Requirements (Guzzle, MongoDB, ext-mongodb, No Laravel Integration)
README.md[32-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The README’s runtime dependency line documents Guzzle as `^7.10 || ^8.0`, but the compliance checklist requires 2.0+ documentation to specify Guzzle `^8.0`.

## Issue Context
This is a public-facing documentation statement that sets user expectations for supported/required dependency versions.

## Fix Focus Areas
- README.md[32-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Gitleaks ignores all .txt 🐞 Bug ⛨ Security
Description
The gitleaks allowlist matches any path ending in .txt, excluding those files repo-wide from
secret scanning and potentially letting real secrets slip through on push/scheduled/manual scans.
The secret-scanning workflow runs gitleaks detect using this configuration (base-branch config on
PRs, current branch config on pushes/schedule), so the reduced coverage affects non-PR events.
Code

.gitleaks.toml[R15-18]

+  '''^coverage/''',               # Local coverage output
+  '''^\.phpdoc/cache/''',         # PHPDoc cache
+  '''\.txt$''',                   # Text files in tests
+  '''^tests/fixtures/''',         # Test fixtures
Evidence
.gitleaks.toml explicitly exempts all .txt files, and the workflow runs gitleaks with that
config (for PRs it loads base-SHA config; for other events it uses the current branch config).

.gitleaks.toml[14-23]
.github/workflows/secret-scanning.yml[32-65]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The allowlist pattern `\.txt$` is global, which exempts *all* `.txt` files from scanning.

### Issue Context
The CI workflow executes `gitleaks detect --config=.../gitleaks.toml`, so the allowlist is applied in CI (notably for push/schedule/workflow_dispatch, and PRs use the trusted base-branch config).

### Fix Focus Areas
- Replace `'''\.txt$'''` with a narrower path-scoped pattern (e.g., `^tests/fixtures/.*\.txt$` or the specific directories where `.txt` files are intentionally safe).
- If the intent is “text files in tests”, encode that intent in the regex/path allowlist instead of file extension alone.

### Fix Focus Areas (code pointers)
- .gitleaks.toml[14-23]
- .github/workflows/secret-scanning.yml[32-65]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread README.md
composer require jooservices/client
```

Runtime dependencies include Guzzle (`^7.10 || ^8.0`), `jooservices/exceptions` (`^0.5`), Monolog, and `mongodb/mongodb` (`^2.0`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Readme lists guzzle ^7.10 📘 Rule violation ⚙ Maintainability

The updated README states runtime support for Guzzle ^7.10 || ^8.0, which contradicts the
compliance requirement that 2.0+ documentation specify Guzzle ^8.0 as the dependency requirement.
This can mislead integrators about the required major version for 2.0+ usage and support
expectations.
Agent Prompt
## Issue description
The README’s runtime dependency line documents Guzzle as `^7.10 || ^8.0`, but the compliance checklist requires 2.0+ documentation to specify Guzzle `^8.0`.

## Issue Context
This is a public-facing documentation statement that sets user expectations for supported/required dependency versions.

## Fix Focus Areas
- README.md[32-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +19 to +21
* @return bool true if this caller may send the probe; false if another probe is in flight
*/
public function tryClaimProbe(): bool;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Statestoreinterface api break 🐞 Bug ⚙ Maintainability

StateStoreInterface now requires tryClaimProbe(), which is a breaking change for any downstream
custom state-store implementations and can cause fatal interface-mismatch errors on upgrade. Docs
explicitly describe custom StateStoreInterface implementations as a supported scalability path,
but this release is targeting v2.2.0 (minor).
Agent Prompt
### Issue description
A new required method (`tryClaimProbe()`) was added to the public `StateStoreInterface`, which breaks any consumer implementation of that interface.

### Issue Context
The docs encourage implementing custom `StateStoreInterface` backends for horizontal scaling, so this interface is part of the supported extension surface.

### Fix Focus Areas
- Revert the breaking interface change by removing `tryClaimProbe()` from `StateStoreInterface` and introducing an *optional* interface (e.g., `HalfOpenProbeStoreInterface`) that defines `tryClaimProbe()`.
- Update built-in stores (`InMemoryStateStore`, `Psr16StateStore`) to implement the optional interface.
- Update `CircuitBreakerMiddleware` to call `tryClaimProbe()` only when the resolved store implements the optional interface (or via `method_exists`), otherwise proceed without single-flight gating.

### Fix Focus Areas (code pointers)
- src/Resilience/Contracts/StateStoreInterface.php[7-26]
- src/Middleware/CircuitBreakerMiddleware.php[28-40]
- src/Resilience/Storage/InMemoryStateStore.php[9-93]
- src/Resilience/Storage/Psr16StateStore.php[17-118]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +109 to +112
$state['probeInFlight'] = true;
$this->writeState($state);

return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. Probe claim lacks expiry 🐞 Bug ☼ Reliability

Psr16StateStore::tryClaimProbe() persists a probeInFlight flag with no lease/expiry; if the
worker that claimed the probe crashes or is killed before reporting success/failure, subsequent
half-open attempts can be rejected indefinitely until cache eviction/manual reset.
CircuitBreakerMiddleware rejects requests when tryClaimProbe() fails and does so before entering
its try/catch, so callers don’t execute any automatic cleanup path.
Agent Prompt
### Issue description
`probeInFlight` can become a stale lock in shared caches: it is written with no lease/expiry and is only cleared on success/failure paths that won’t run if the claiming process terminates.

### Issue Context
`CircuitBreakerMiddleware` blocks half-open calls when `tryClaimProbe()` returns false, which makes a stale `probeInFlight=true` effectively wedge the circuit-breaker in practice.

### Fix Focus Areas
- Store a `probeClaimedAt` timestamp alongside `probeInFlight`.
- In `tryClaimProbe()`, if `probeInFlight` is true but `probeClaimedAt` is older than a configured/max lease duration, clear it and allow a new claim.
- Introduce a configurable probe lease duration (e.g., on `CircuitBreakerConfig`) or derive a safe default (e.g., based on request timeout/deadline) so the stale-probe window is bounded.
- Ensure both `Psr16StateStore` and `InMemoryStateStore` follow the same stale-claim semantics.

### Fix Focus Areas (code pointers)
- src/Middleware/CircuitBreakerMiddleware.php[28-67]
- src/Resilience/Storage/Psr16StateStore.php[58-157]
- src/Resilience/Storage/InMemoryStateStore.php[11-93]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread .gitleaks.toml
Comment on lines +15 to +18
'''^coverage/''', # Local coverage output
'''^\.phpdoc/cache/''', # PHPDoc cache
'''\.txt$''', # Text files in tests
'''^tests/fixtures/''', # Test fixtures

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

4. Gitleaks ignores all .txt 🐞 Bug ⛨ Security

The gitleaks allowlist matches any path ending in .txt, excluding those files repo-wide from
secret scanning and potentially letting real secrets slip through on push/scheduled/manual scans.
The secret-scanning workflow runs gitleaks detect using this configuration (base-branch config on
PRs, current branch config on pushes/schedule), so the reduced coverage affects non-PR events.
Agent Prompt
### Issue description
The allowlist pattern `\.txt$` is global, which exempts *all* `.txt` files from scanning.

### Issue Context
The CI workflow executes `gitleaks detect --config=.../gitleaks.toml`, so the allowlist is applied in CI (notably for push/schedule/workflow_dispatch, and PRs use the trusted base-branch config).

### Fix Focus Areas
- Replace `'''\.txt$'''` with a narrower path-scoped pattern (e.g., `^tests/fixtures/.*\.txt$` or the specific directories where `.txt` files are intentionally safe).
- If the intent is “text files in tests”, encode that intent in the regex/path allowlist instead of file extension alone.

### Fix Focus Areas (code pointers)
- .gitleaks.toml[14-23]
- .github/workflows/secret-scanning.yml[32-65]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants