Skip to content

feat: make the algorithm, checker and serializer managers immutable - #703

Merged
Spomky merged 1 commit into
4.3.xfrom
feature/immutable-managers
Aug 29, 2026
Merged

feat: make the algorithm, checker and serializer managers immutable#703
Spomky merged 1 commit into
4.3.xfrom
feature/immutable-managers

Conversation

@Spomky

@Spomky Spomky commented Aug 28, 2026

Copy link
Copy Markdown
Member

Target branch: 4.3.x
Resolves issue #688

  • It is a Bug fix
  • It is a New feature
  • It is related to dependencies

Includes:

  • Breaks BC
  • Deprecations

A manager expresses a policy — "these algorithms and no others". AlgorithmManager::add() let any consumer holding
the injected service widen that policy for every other consumer, so it is deprecated in favour of an immutable API.

AlgorithmManager

// before: mutates the shared service
$manager->add(new None());

// after: explicit, local, no side effect
$manager = $manager->with(new None());
  • with(Algorithm ...$algorithms): self returns a new manager supporting the current algorithms plus the given ones.
    An algorithm whose name is already supported replaces the previous one, as add() did.
  • add() still works and still mutates, but triggers a deprecation. The constructor does not go through it any more,
    so building a manager is silent.
  • $algorithms stays writable: readonly there would break the deprecated add().

The other managers

HeaderCheckerManager, ClaimCheckerManager, JWSSerializerManager and JWESerializerManager already had a private
add(), so they only needed their state closed: the properties are now readonly and filled once by the constructor,
and the now-unused private add()/addTokenTypeSupport() methods are gone. Both serializer managers, already final,
became readonly classes (asked for by Rector, and equivalent here since they hold a single property).

The two checker managers stay non-final: the bundle extends them to dispatch events. Their docblock records that
they will be final in 5.0.0.

No public signature changed and no behaviour changed for existing callers, so nothing breaks. with() was
deliberately not added to the four other managers: their add() was never public, and 5.0.0 is where the whole family
gets the same treatment.

Tests

  • AlgorithmManagerTest covers with() (new instance, original untouched, several algorithms at once, replacement by
    name, no deprecation) and add() (deprecation triggered, mutation preserved).
  • ImmutableManagerStateTest asserts the state of the four other managers is readonly, so a later change cannot
    quietly reopen it.

Full suite, ECS, PHPStan, Rector and Deptrac are green; the managers were also smoke-tested on PHP 8.2, the minimum
supported version, for the readonly class syntax.

@Spomky Spomky self-assigned this Aug 28, 2026
@Spomky Spomky added the feature label Aug 28, 2026
@Spomky Spomky added this to the 4.3.0 milestone Aug 28, 2026
@Spomky Spomky linked an issue Aug 28, 2026 that may be closed by this pull request
A manager expresses a policy ("these algorithms and no others"), so it must
not be possible for a consumer to widen it. AlgorithmManager::add() mutated a
service that is usually shared: it is deprecated in favour of with(), which
returns a new manager and leaves the current one untouched.

The state of the checker and serializer managers is now readonly, and both
serializer managers, already final, are readonly classes.
@Spomky
Spomky force-pushed the feature/immutable-managers branch from 5dfc8e3 to 2d5fa88 Compare August 29, 2026 16:39
@Spomky
Spomky merged commit 258f8a8 into 4.3.x Aug 29, 2026
3 checks passed
@Spomky
Spomky deleted the feature/immutable-managers branch August 29, 2026 16:40
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.

Make the algorithm, checker and serializer managers immutable

1 participant