Skip to content

chore: update dependencies - #678

Merged
vincentchalamon merged 10 commits into
fix/keycloak-wildcard-redirect-urisfrom
chore/update-dependencies
Jul 30, 2026
Merged

chore: update dependencies#678
vincentchalamon merged 10 commits into
fix/keycloak-wildcard-redirect-urisfrom
chore/update-dependencies

Conversation

@vincentchalamon

@vincentchalamon vincentchalamon commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Stacked on #676, which targets 4.3 directly now that #675 is merged. The base retargets automatically when #676 lands.

Summary

Ops, backend and frontend brought up to date, one commit per step so a regression can be traced to a single bump. Each commit was gated before the next one was written; whatever could not pass is left out and documented below rather than forced through.

commit content gate
chore(ops) FrankenPHP 1.12.41.12.6, E2E mock server follows node:lts instead of pinning node 22 PHPUnit · PHPStan · Rector · schema · E2E
chore(helm) external-dns chart 1.20.01.21.1 helm lint · helm template on both host shapes
chore(api) api-platform 4.3.144.3.17, doctrine-bundle 3.2.43.3.1, phpunit 13.2.6, rector 2.5.8, phpstan 2.2.7, graphql-php 15.37.1, foundry 2.11.0 PHPUnit · PHPStan · Rector · php-cs-fixer
chore(api) Symfony 8.0.*8.1.* PHPUnit · PHPStan · Rector · schema · OpenAPI · E2E
chore(pwa) react-admin/ra-* 5.15.x, next 16.2.12, better-auth 1.6.25, react 19.2.8, tailwind 4.3.3, react-hook-form 7.83.0, pg 8.22.0, pnpm 11.18.0 lint · build · E2E
chore(pwa) TypeScript 5.96.0 tsc --noEmit · lint · build
chore(pwa) MUI 7.39.2 lint · build · E2E · visual check
chore(pwa) @types/node aligned on the Node LTS the images run build
chore(pwa) drop unused @babel/core and @popperjs/core lint · build · E2E
chore(e2e) Playwright 1.501.62 + the CI runner image tag E2E, both tag groups

Adjustments the bumps required

  • Rector 2.5.8 adds NegatedAndsToPositiveOrsRector, which rewrites two existing test mocks. rector --dry-run is a CI gate, so the rewrite is applied.
  • Symfony 8.1 reports a more precise denormalization error for backed enums. BookTest expectations are now derived from BookCondition::cases() instead of hardcoding the old "must belong to a backed enumeration" wording, so they follow the enum.
  • TypeScript 6 rejects the deprecated target: es5 (TS5107). The project no longer needs it: moduleResolution moves to bundler as Next expects, and spreading the matchAll iterator no longer needs downlevel iteration, so the @ts-expect-error covering it is dropped.
  • MUI 9 (there is no v8; react-admin already peers on ^9) has three breaking changes to follow: Box system props move to sx, Menu replaces MenuListProps with slotProps.list, and the PersonOutline icon is renamed PersonOutlined. A sweep for other renamed slot props and Grid/Stack system props came back empty.
  • Playwright 1.62 also required bumping mcr.microsoft.com/playwright:v1.58.0-noble in ci.yml, otherwise the runner would keep installing 1.58 while package.json asks for 1.62.

Deliberately left out

  • ESLint 10eslint-plugin-react@7.37.5, the latest release, peers at ^9.7 and crashes under ESLint 10 with contextOrFilename.getFilename is not a function. It reaches us through eslint-config-next, so there is nothing to override sensibly.
  • TypeScript 7eslint-config-next bundles typescript-eslint@^8.46.0, whose peer range is >=4.8.4 <6.1.0. TS 6 is the highest reachable version today.
  • @types/node 26 — the latest published, but the types should describe the runtime, and both images build on node:lts (Node 24). The previous ^25 matched no version of Node in use, so this is an alignment rather than a downgrade.
  • PostgreSQL — left on 16 as agreed. Worth a separate issue: templates/postgresql.yaml defaults the CloudNativePG image tag to 17 while values.yaml pins 16.
  • Symfony recipe updates — available for several packages, some predating this PR. Applying them would spread config churn across an already large upgrade; better handled on their own.
  • GitHub Actions — every action is already on its latest major (checked one by one against upstream releases). The one exception, the archived grafana/k6-action, is ci: replace archived grafana/k6-action with setup-k6-action #677.

Verification

Run on the composed stacks, not just unit level:

  • Backend: PHPUnit 126 tests / 576 assertions OK · PHPStan no errors · rector --dry-run clean · doctrine:schema:validate in sync · api:openapi:export | redocly lint valid · php-cs-fixer 0 of 76 files · hadolint clean on the three Dockerfiles.
  • E2E (compose.yaml:compose.prod.yaml:compose.e2e.yaml, images rebuilt, realm reimported, fixtures reloaded, @read and @write each on a fresh stack as CI does): @read 24 passed / 2 flaky, @write 8 passed / 3 flaky, 0 failed. Same flaky set as before this PR — login-page timing, all green on retry.
  • Frontend: pnpm lint, pnpm build and tsc --noEmit clean after every step; MUI 9 checked visually on the public pages, and functionally through the admin E2E specs, which drive lists, forms, autocompletes, menus and pagination.
  • Helm: helm lint plus helm template on demo.api-platform.com and pr-42-demo.api-platform.com.

🤖 Generated with Claude Code

vincentchalamon and others added 10 commits July 30, 2026 15:21
FrankenPHP 1.12.4 -> 1.12.6, and the E2E mock server follows the node:lts tag
already used by the PWA image instead of pinning node 22.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
api-platform 4.3.14 -> 4.3.17, doctrine/doctrine-bundle 3.2.4 -> 3.3.1,
phpunit 13.2.1 -> 13.2.6, rector 2.4.6 -> 2.5.8, phpstan 2.2.2 -> 2.2.7,
webonyx/graphql-php 15.33.1 -> 15.37.1, zenstruck/foundry 2.10.1 -> 2.11.0.

Rector 2.5.8 adds NegatedAndsToPositiveOrsRector, which rewrites two test mocks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The lock was already half on 8.1 through transitive Dependabot bumps (#655, #656),
while composer.json still pinned 8.0.*.

Symfony 8.1 reports a more precise denormalization error for backed enums, so the
BookTest expectations are derived from BookCondition::cases() instead of the old
"must belong to a backed enumeration" wording.

Recipe updates are available for several packages, some predating this change, and
are deliberately left out to keep the upgrade reviewable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
react-admin and the ra-* packages to 5.15.x, next 16.2.12, better-auth 1.6.25,
react 19.2.8, tailwindcss 4.3.3, react-hook-form 7.83.0, pg 8.22.0 and the
remaining patches.

packageManager follows pnpm 11.18.0: 11.8.0 and 11.18.0 disagree on the importer
specifier recorded for a direct dependency that an override also covers, so the
postcss range is aligned with its override to keep the lockfile stable whichever
version writes it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TypeScript 6 rejects the deprecated `target: es5` (TS5107), which the project no
longer needs: `moduleResolution` follows `bundler` as Next expects, and spreading
the `matchAll` iterator no longer requires downlevel iteration, so the
`@ts-expect-error` that covered it is dropped.

TypeScript 7 is not reachable yet: eslint-config-next bundles typescript-eslint 8,
whose peer range is `>=4.8.4 <6.1.0`, so it would break `pnpm lint`.

ESLint 10 is left out for the same class of reason: eslint-plugin-react 7.37.5,
the latest release, peers at `^9.7` and crashes under ESLint 10 with
"contextOrFilename.getFilename is not a function".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
MUI has no v7 -> v8 step, 9.2.0 is the next major. react-admin 5.15.1 and
ra-ui-materialui already peer on `^5.16.12 || ^6 || ^7 || ^9`.

Three breaking changes had to be followed:

- Box no longer accepts system props, they move to `sx`.
- Menu replaces `MenuListProps` with `slotProps.list`.
- The icon named `PersonOutline` is now `PersonOutlined`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
26.1.2 is the latest published, but the types must describe the runtime: both
images build on `node:lts`, currently Node 24. The previous `^25` matched no
version of Node in use.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neither is used by the project: there is no babel config in the repository and
Next 16 compiles through SWC, while @popperjs/core is referenced by no source
file. Both remain in the tree as transitive dependencies, so declaring them
brought nothing but a spurious `@babel/core` 7 -> 8 major to consider.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The CI runner image tag follows, otherwise the container would keep installing
1.58 while package.json asks for 1.62. @types/node tracks the Node LTS the
images run on, like the PWA.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vincentchalamon
vincentchalamon force-pushed the fix/keycloak-wildcard-redirect-uris branch from d22f103 to 707181b Compare July 30, 2026 13:22
@vincentchalamon
vincentchalamon force-pushed the chore/update-dependencies branch from 5e13f86 to 2cd0a3d Compare July 30, 2026 13:22
@vincentchalamon
vincentchalamon merged commit d19cd22 into fix/keycloak-wildcard-redirect-uris Jul 30, 2026
7 checks passed
@vincentchalamon
vincentchalamon deleted the chore/update-dependencies branch July 30, 2026 13:30
vincentchalamon added a commit that referenced this pull request Jul 30, 2026
* fix(helm): upgrade keycloak to 26.7

Keycloak 26.4 is within the vulnerable range of CVE-2026-7504 /
GHSA-rp95-xpg9-c2cq, fixed upstream in 26.6.2. keycloak-config-cli follows to
6.5.1-26.

Two upstream behaviour changes had to be handled to make the bump work:

- Since 26.6, JavaScript-based policies require the `scripts` feature, otherwise
  importing the realm fails with "Couldn't find policy provider with type
  [script-owner-policy.js]". It is enabled at build time for `start --optimized`
  and through KC_FEATURES for `start-dev`, which re-runs the augmentation and
  drops build-time options.
- Since 26.6.2 the Protection API forces the owner of a resource to the resource
  server itself (keycloak/keycloak#49910, confirmed intended and permanent by the
  maintainer), which broke the "Owner" policy: reviews became owned by the
  `api-platform-api` client instead of their author, and the front-office review
  permissions were denied. Resource creation, lookup and deletion now go through
  the Admin API as recommended upstream, and the service account is granted the
  single `manage-authorization` role this requires. The client's internal id comes
  from configuration, so no `view-clients` role is needed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore: update dependencies (#678)

* chore(ops): update docker base images

FrankenPHP 1.12.4 -> 1.12.6, and the E2E mock server follows the node:lts tag
already used by the PWA image instead of pinning node 22.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(helm): update external-dns chart to 1.21.1

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(api): update composer dependencies

api-platform 4.3.14 -> 4.3.17, doctrine/doctrine-bundle 3.2.4 -> 3.3.1,
phpunit 13.2.1 -> 13.2.6, rector 2.4.6 -> 2.5.8, phpstan 2.2.2 -> 2.2.7,
webonyx/graphql-php 15.33.1 -> 15.37.1, zenstruck/foundry 2.10.1 -> 2.11.0.

Rector 2.5.8 adds NegatedAndsToPositiveOrsRector, which rewrites two test mocks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(api): upgrade symfony to 8.1

The lock was already half on 8.1 through transitive Dependabot bumps (#655, #656),
while composer.json still pinned 8.0.*.

Symfony 8.1 reports a more precise denormalization error for backed enums, so the
BookTest expectations are derived from BookCondition::cases() instead of the old
"must belong to a backed enumeration" wording.

Recipe updates are available for several packages, some predating this change, and
are deliberately left out to keep the upgrade reviewable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(pwa): update minor and patch dependencies

react-admin and the ra-* packages to 5.15.x, next 16.2.12, better-auth 1.6.25,
react 19.2.8, tailwindcss 4.3.3, react-hook-form 7.83.0, pg 8.22.0 and the
remaining patches.

packageManager follows pnpm 11.18.0: 11.8.0 and 11.18.0 disagree on the importer
specifier recorded for a direct dependency that an override also covers, so the
postcss range is aligned with its override to keep the lockfile stable whichever
version writes it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(pwa): upgrade typescript to 6

TypeScript 6 rejects the deprecated `target: es5` (TS5107), which the project no
longer needs: `moduleResolution` follows `bundler` as Next expects, and spreading
the `matchAll` iterator no longer requires downlevel iteration, so the
`@ts-expect-error` that covered it is dropped.

TypeScript 7 is not reachable yet: eslint-config-next bundles typescript-eslint 8,
whose peer range is `>=4.8.4 <6.1.0`, so it would break `pnpm lint`.

ESLint 10 is left out for the same class of reason: eslint-plugin-react 7.37.5,
the latest release, peers at `^9.7` and crashes under ESLint 10 with
"contextOrFilename.getFilename is not a function".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(pwa): upgrade mui to 9

MUI has no v7 -> v8 step, 9.2.0 is the next major. react-admin 5.15.1 and
ra-ui-materialui already peer on `^5.16.12 || ^6 || ^7 || ^9`.

Three breaking changes had to be followed:

- Box no longer accepts system props, they move to `sx`.
- Menu replaces `MenuListProps` with `slotProps.list`.
- The icon named `PersonOutline` is now `PersonOutlined`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(pwa): align @types/node with the node lts runtime

26.1.2 is the latest published, but the types must describe the runtime: both
images build on `node:lts`, currently Node 24. The previous `^25` matched no
version of Node in use.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(pwa): remove unused @babel/core and @popperjs/core

Neither is used by the project: there is no babel config in the repository and
Next 16 compiles through SWC, while @popperjs/core is referenced by no source
file. Both remain in the tree as transitive dependencies, so declaring them
brought nothing but a spurious `@babel/core` 7 -> 8 major to consider.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(e2e): upgrade playwright to 1.62

The CI runner image tag follows, otherwise the container would keep installing
1.58 while package.json asks for 1.62. @types/node tracks the Node LTS the
images run on, like the PWA.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>

* fix(helm): give keycloak enough memory to survive a rollout

The container limit was 500Mi with a 400Mi request, which leaves no headroom:
importing the demo realm, with its authorization services and JavaScript policy,
leaves the JVM just under the limit, so the pod is OOMKilled during rollout and
the post-upgrade keycloak-config-cli hook then times out waiting for a Keycloak
that never becomes ready.

Measured locally with the demo realm imported and `start --optimized`:

| version | limit 500Mi | limit 768Mi |
| --- | --- | --- |
| 26.4.7 | OOMKilled | 671Mi (87%) |
| 26.7.0 | 496Mi (99%) | 553Mi (72%), 590Mi under admin API load |

This is not a consequence of the version bump: 26.7 is in fact leaner than 26.4
here. The limit was simply too small for both, and any rollout was one allocation
away from being killed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(helm): drop the built-in realm-management client from the realm

realm-demo.json is a full realm export, so it carries Keycloak's own built-in
clients. keycloak-config-cli therefore tries to update `realm-management`, which
Keycloak 26.7 forbids:

    Update client 'realm-management' in realm 'demo'
    Cannot update client 'realm-management' in realm 'demo': HTTP 403 Forbidden

The post-upgrade hook then fails on every retry and the release never completes.
26.4 allowed the update, which is why this only shows up now.

Keycloak recreates `realm-management` and its roles itself when the realm is
created, so removing them from the export changes nothing functionally: the
service account still resolves its `manage-authorization` role against the
auto-created client. The other built-in clients are left in place — only
`realm-management` is protected, and config-cli updates the rest without
complaint.

Verified against 26.7.0 with keycloak-config-cli 6.5.1-26: import succeeds on a
fresh realm and is idempotent on the second pass, which is what the
post-install/post-upgrade hook needs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(helm): pin keycloak to 26.6 instead of 26.7

26.7.0 refuses to manage any realm role literally named `admin`, in any realm:

    // RolePermissions.canManage(RoleModel), 26.7.0
    if (role.getContainer() instanceof RealmModel) {
        return root.realm().canManageRealm() && !isRealmAdminRole(role);
    }

    private boolean isRealmAdminRole(RoleModel role) {
        return role.getContainer() instanceof RealmModel
            && List.of(AdminRoles.ADMIN, AdminRoles.CREATE_REALM).contains(role.getName());
    }

The check is purely name-based and ignores which realm the role belongs to, so the
demo realm's own `admin` role becomes unmanageable: `PUT /admin/realms/demo/roles/admin`
answers 403 even to a full master-realm admin, while `roles/user` and a freshly
created `admin2` update fine. keycloak-config-cli hits it as soon as that role has
drifted from the file, so the post-upgrade hook fails on every retry.

`isRealmAdminRole` exists only in 26.7.0 — it is absent from 26.6.4, 26.5.7 and
26.4.7 — and the advisory only requires >= 26.6.2. 26.6 therefore closes
CVE-2026-7504 without the regression, and keeps every other adjustment relevant:
26.6 already requires the `scripts` feature, and its Protection API already forces
the resource owner to the resource server.

Verified on 26.6.4: realm imported at startup, keycloak-config-cli succeeds and is
idempotent on a second pass, review resources are owned by their author again, and
the E2E @Write suite passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant