Skip to content

[Conflicts] Merge main into next - #6249

Open
vivid-planet-bot wants to merge 48 commits into
nextfrom
merge-main-into-next
Open

[Conflicts] Merge main into next#6249
vivid-planet-bot wants to merge 48 commits into
nextfrom
merge-main-into-next

Conversation

@vivid-planet-bot

@vivid-planet-bot vivid-planet-bot commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

This is an automated pull request to merge changes from main into next. It has merge conflicts. To resolve conflicts, check out the branch merge-main-into-next locally, make any necessary changes to conflicting files, and commit and publish your changes.

…toolbar (#6247)

The `link` toolbar buttons were rendered after the
`non-breaking-space`/`soft-hyphen` buttons in the TipTap rich text block
toolbar instead of before them; this swaps them back.

|Before|After|
|------|-----|
|<img width="384" height="238" alt="Bildschirmfoto 2026-08-27 um 11 44
48"
src="https://github.com/user-attachments/assets/0a8d2222-f951-4b35-9442-f73c64f45e0a"
/>|<img width="370" height="404" alt="Bildschirmfoto 2026-08-27 um 11 26
04"
src="https://github.com/user-attachments/assets/3c72f32e-e938-48d1-a7eb-267cfadb2c58"
/>|

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

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. 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: Path: .coderabbit.yml

Review profile: CHILL

Plan: Team

Run ID: 2ced74ac-99c3-4fad-98a9-ff240c9a2adc

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.

## Status quo

The supported versions table in `SECURITY.md` still lists `9.x` as
supported and does not mention `10.x` at all, so it tells users to stay
on a version that no longer receives security updates and gives no
guidance for the current major.

## Change

- `10.x` and later are marked as supported.
- `9.x` is marked as unsupported, with a note that `10.x` is a largely
compatible replacement because every breaking change in it is part of
the COMET -> Dextinity rename. The note links the [migration guide from
v9 to
v10](https://cms-docs.dextinity.com/docs/migration-guide/migration-from-v9-to-v10).
- Support for `8.x` stays unchanged (until 2027-07-07).

No changeset, as this is a documentation-only change and does not
warrant a package release.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01UwicBS8jUVYsZqGmrFhxyB)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
#6079)

Task: https://vivid-planet.atlassian.net/browse/COM-3100

## Summary
This change allows DAM files to be replaced with files of the same
category rather than requiring an exact mimetype match. For example, a
JPEG image can now be replaced with a WebP, and an MP3 audio file can be
replaced with an OGG file, as long as they belong to the same category.

## Key Changes

- **New file categorization utility**: Created `getDamFileCategory()`
helper function in both API and admin packages that categorizes
mimetypes into five categories:
  - `pixelImage`: JPEG, PNG, WebP, GIF, etc.
  - `svgImage`: SVG (kept separate from pixel images)
  - `audio`: MP3, OGG, WAV, etc.
  - `video`: MP4, WebM, QuickTime, etc.
  - `document`: PDF, DOCX, VTT, ZIP, and other files

- **Updated file replacement logic**: Modified
`FilesService.replaceFile()` to:
- Validate that the replacement file belongs to the same category
instead of checking for exact mimetype match
- Throw `CometValidationException` instead of generic `Error` for better
error handling
- Automatically adjust the file's extension to match the new file (e.g.,
`photo.jpg` → `photo.webp`)
- Create image metadata if the replacement file is an image but the
original wasn't
- Prevent replacement if a file with the new name already exists in the
same folder

- **Updated admin UI**: 
- Modified `ReplaceFileButton` to accept all mimetypes in the same
category as the current file
  - Improved error messages to be more user-friendly and informative
  - Better error handling with proper cleanup in finally block

- **Refactored mime type filtering**: Simplified
`useDamAcceptedMimeTypes()` to use the new `getDamFileCategory()` helper
instead of individual type-checking functions

- **Added comprehensive tests**: Created test suites for the new
`getDamFileCategory()` function in both packages

## Notable Implementation Details

- The `getDamFileCategory()` function is duplicated between API and
admin packages with a prominent comment warning about keeping them in
sync
- File URLs and usages remain unchanged during replacement; only the
file extension is adjusted
- The implementation properly handles cases where the original file had
no image metadata but the replacement does


## Screenshots

| Original | Replaced |
|----|----|
| <img width="1600" height="1000" alt="1beforejpeg"
src="https://github.com/user-attachments/assets/bf4f6ea7-c55e-4717-9dcd-d23288472589"
/> | <img width="1600" height="1000" alt="2afterwebp"
src="https://github.com/user-attachments/assets/8ce4e609-7401-43ff-96f1-03823df5c4e1"
/> |


| Files with same name/different format | Error message after replacing
|
|----|----|
| <img width="1600" height="1000" alt="3folderwithnameconflict"
src="https://github.com/user-attachments/assets/69e43407-31e8-431c-87ae-117ed9b6b407"
/> | <img width="1600" height="1000" alt="4errorfilenamealreadyexists"
src="https://github.com/user-attachments/assets/43387853-e794-4552-a235-593f3f8082d9"
/> |

---------

Co-authored-by: Claude <noreply@anthropic.com>
The setup guide still described the Brevo Module as it was published
from the standalone comet-brevo-module repository: it referenced v3, the
old repository, package names that never existed under this scope
(`@vivid-planet/comet-brevo-*`) and the removed brevo-mail-rendering
package.

- Reference `@dextinity/brevo-api` and `@dextinity/brevo-admin` v10 and
the dextinity monorepo
- Replace the mail rendering section with `@dextinity/mail-react`,
including the render endpoint and block preview the site has to provide
- Document the scope, the entity factories and the
`EmailCampaignContentBlock`
- Document the optional `BlacklistedContacts` and `BrevoEmailImportLog`
entities
- Document the `BrevoConfigProvider`
- Add the mandatory `ecgRtrList` config and the `text/csv` mime type
requirement
- Rename the target group fragment to `BrevoTargetGroup`
- Fix the localhost link to the optional features page

COM-3110

Deploy preview:
https://deploy-preview-6143.cms-docs.dextinity.com/docs/features-modules/brevo-module/

---------

Co-authored-by: Claude <noreply@anthropic.com>
## Status quo

TypeScript's `strict` mode is set for the api and site packages,
`cms-admin`, `brevo-admin`, `admin-generator`, `demo/api` and
`demo/site`, but not for the rest — so type checking differs from
package to package.

## Change

`cli`, `admin-icons`, `admin-color-picker` and `admin-date-time` already
compile under `strict` mode with zero errors, so they only need the
flag. No code changes, no behaviour change, no changeset.

First step of enabling it package by package; the rest follow one per
pull request, and the flag moves to `tsconfig.core.json` once they all
carry it.

## Further information

- Task: https://vivid-planet.atlassian.net/browse/COM-1079

Co-authored-by: Claude <noreply@anthropic.com>
VPS-thodax and others added 2 commits August 31, 2026 12:28
## Status quo

TypeScript's `strict` mode is set for most of the repo, but
`eslint-plugin` sets no strict flag at all.

## Change

Switch it on. `no-other-module-relative-import` needed two narrowing
guards to compile, neither changes behaviour. The rule's own tests pass
unchanged.

No changeset, since nothing about the published package changes. One
package per pull request, and the flag moves to `tsconfig.core.json`
once they all carry it.

## Further information

- Task: https://vivid-planet.atlassian.net/browse/COM-1079

Co-authored-by: Claude <noreply@anthropic.com>
## Status quo

Strict mode is not enabled everywhere in this repo. The Storybook has a
standalone `tsconfig.json` that sets `noImplicitAny` and
`strictNullChecks` individually.

## Change

Enable `strict`, which implies both flags, so they are replaced by the
single one.

No changeset: `dextinity-storybook` is private.

## Further information

- Task: https://vivid-planet.atlassian.net/browse/COM-1079


---
_Generated by [Claude
Code](https://claude.ai/code/session_01JkyZV6LzEij2nv4VkArNxU)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
@vivid-planet-bot
vivid-planet-bot force-pushed the merge-main-into-next branch 2 times, most recently from ccf3c4d to 9e52a31 Compare August 31, 2026 10:32
Add a `DamVideoBlock` section to the block factories docs, documenting
the `createDamVideoBlock` factory and its `supports` option.

https://vivid-planet.atlassian.net/browse/PHSB2C-13669

---------

Co-authored-by: Claude <noreply@anthropic.com>
## Motivation

A large part of the v8 → v9 changes are new `@comet/eslint-config` rules
rather than runtime changes. They bloat the diff and make it difficult
to review.

## Solution

Add a `Prerequisites` section that recommends bumping
`@comet/eslint-config` to v9 on its own — all other `@comet/*` packages
stay on v8 — and merging that to `main` before starting the migration.

Besides the bump and the autofixes, it covers the parts that aren't
obvious:

- Reconciling the project's `eslint.config.mjs` with the shared config —
in particular that a local `no-restricted-imports` must extend
`restrictedImportPaths`/`restrictedImportPatterns` instead of replacing
them, since replacing them silently drops the `@comet/*/lib`
restriction.
- Cross-links to the three sections of the guide that are pure lint
changes and can already be done on v8.
- Suppressing the violations that only v9 can fix behind a `//
TODO(comet-v9):` marker, to be resolved during the migration.

## Verification

The three new cross-links resolve — `build:docusaurus` reports no new
broken anchors (the four it lists are pre-existing, on other pages).

---
_Generated by [Claude
Code](https://claude.ai/code/session_013r3BHWU4po8mhSoqmzHpU9)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [next](https://nextjs.org)
([source](https://redirect.github.com/vercel/next.js)) | [`16.2.10` →
`16.2.11`](https://renovatebot.com/diffs/npm/next/16.2.10/16.2.11) |
![age](https://developer.mend.io/api/mc/badges/age/npm/next/16.2.11?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/next/16.2.10/16.2.11?slim=true)
|

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](../issues/2742) for more information.

---

### Next.js: Denial of Service in App Router using Server Actions
[CVE-2026-64641](https://nvd.nist.gov/vuln/detail/CVE-2026-64641) /
[GHSA-m99w-x7hq-7vfj](https://redirect.github.com/advisories/GHSA-m99w-x7hq-7vfj)

<details>
<summary>More information</summary>

#### Details
##### Impact

Crafted requests targeting Next.js applications using App Router with at
least one Server Action can lead to excessive CPU usage blocking
processing of further requests in the same process.

##### Workarounds

No workaround exists besides upgrading. Applications using Pages Router
or not using Server Actions are not vulnerable.

#### Severity
- CVSS Score: 8.2 / 10 (High)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N`

#### References
-
[https://github.com/vercel/next.js/security/advisories/GHSA-m99w-x7hq-7vfj](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-m99w-x7hq-7vfj)
-
[https://github.com/vercel/next.js/pull/96013](https://redirect.github.com/vercel/next.js/pull/96013)
-
[https://github.com/vercel/next.js/commit/019628571641dec57aaf349ba0c360e3964e6f12](https://redirect.github.com/vercel/next.js/commit/019628571641dec57aaf349ba0c360e3964e6f12)
-
[https://github.com/vercel/next.js/releases/tag/v15.5.21](https://redirect.github.com/vercel/next.js/releases/tag/v15.5.21)
-
[https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
-
[https://github.com/advisories/GHSA-m99w-x7hq-7vfj](https://redirect.github.com/advisories/GHSA-m99w-x7hq-7vfj)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-m99w-x7hq-7vfj)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Next.js: Middleware / Proxy bypass in App Router applications using
Turbopack and single locale
[CVE-2026-64642](https://nvd.nist.gov/vuln/detail/CVE-2026-64642) /
[GHSA-6gpp-xcg3-4w24](https://redirect.github.com/advisories/GHSA-6gpp-xcg3-4w24)

<details>
<summary>More information</summary>

#### Details
##### Impact

Crafted requests targeting Next.js applications using App Router built
with Turbopack and a **single** entry in `config.i18n.locales` can
bypass middleware/proxy based authentication.

##### Workarounds

If you cannot upgrade immediately, enforce authorization in the page's
server-side data path instead of relying solely on middleware.

#### Severity
- CVSS Score: 8.3 / 10 (High)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N`

#### References
-
[https://github.com/vercel/next.js/security/advisories/GHSA-6gpp-xcg3-4w24](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-6gpp-xcg3-4w24)
-
[https://github.com/vercel/next.js/pull/96014](https://redirect.github.com/vercel/next.js/pull/96014)
-
[https://github.com/vercel/next.js/commit/6bf4df14508ad6c0cd46af50c6051ee42f2d9151](https://redirect.github.com/vercel/next.js/commit/6bf4df14508ad6c0cd46af50c6051ee42f2d9151)
-
[https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
-
[https://github.com/advisories/GHSA-6gpp-xcg3-4w24](https://redirect.github.com/advisories/GHSA-6gpp-xcg3-4w24)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-6gpp-xcg3-4w24)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Next.js: Unauthenticated disclosure of internal Server Function
endpoints
[CVE-2026-64643](https://nvd.nist.gov/vuln/detail/CVE-2026-64643) /
[GHSA-955p-x3mx-jcvp](https://redirect.github.com/advisories/GHSA-955p-x3mx-jcvp)

<details>
<summary>More information</summary>

#### Details
##### Impact

In Next.js applications using App Router, Server Actions (`use server`)
or `use cache` endpoints can be disclosed bypassing any authentication
on the pages where these endpoints are usually used.

Server Action IDs can be disclosed to unauthenticated users via publicly
served client artifacts (for example, static chunks containing action
references).

Affected users are applications using App Router + Server Actions.  

By itself, this disclosure is typically a recon/enumeration primitive;
however, it can increase risk when combined with other weaknesses.
 

##### Workarounds

Never assume any authentication claims at the `use cache` or `use
server` boundary. Always authenticate within the boundary.

#### Severity
- CVSS Score: 6.3 / 10 (Medium)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N`

#### References
-
[https://github.com/vercel/next.js/security/advisories/GHSA-955p-x3mx-jcvp](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-955p-x3mx-jcvp)
-
[https://github.com/vercel/next.js/commit/1b0c3ae912a3ad925c60065cc8d55b070fa8bcd3](https://redirect.github.com/vercel/next.js/commit/1b0c3ae912a3ad925c60065cc8d55b070fa8bcd3)
-
[https://github.com/vercel/next.js/commit/ff12a6124e1504f17b62de948b8a553fdecaef7b](https://redirect.github.com/vercel/next.js/commit/ff12a6124e1504f17b62de948b8a553fdecaef7b)
-
[https://github.com/vercel/next.js/releases/tag/v15.5.21](https://redirect.github.com/vercel/next.js/releases/tag/v15.5.21)
-
[https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
-
[https://github.com/advisories/GHSA-955p-x3mx-jcvp](https://redirect.github.com/advisories/GHSA-955p-x3mx-jcvp)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-955p-x3mx-jcvp)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Next.js: Denial of Service in the Image Optimization API using SVGs
[CVE-2026-64644](https://nvd.nist.gov/vuln/detail/CVE-2026-64644) /
[GHSA-q8wf-6r8g-63ch](https://redirect.github.com/advisories/GHSA-q8wf-6r8g-63ch)

<details>
<summary>More information</summary>

#### Details
##### Impact

When self-hosting Next.js with the default image loader, the Image
Optimization API can optimize remotely hosted images if configured (not
enabled by default). If those images contain malicious content, they can
cause CPU exhaustion in `/_next/image` endpoints.

- If you are using `config.images.remotePatterns`, only the patterns in
that array are impacted.
- If you are using `config.images.unoptimized: true`, you are NOT
impacted.
- If you are using `config.images.loader: 'custom'`, you are NOT
impacted.
- If you are using Vercel, you are NOT impacted.

##### Workarounds

If you cannot upgrade immediately, you can avoid the expensive work by
setting `config.experimental.imgOptSkipMetadata : true`.

#### Severity
- CVSS Score: 6.3 / 10 (Medium)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N`

#### References
-
[https://github.com/vercel/next.js/security/advisories/GHSA-q8wf-6r8g-63ch](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-q8wf-6r8g-63ch)
-
[https://github.com/vercel/next.js/pull/96006](https://redirect.github.com/vercel/next.js/pull/96006)
-
[https://github.com/vercel/next.js/commit/93cb90891402fa4c47798d03cb9e05c13233766c](https://redirect.github.com/vercel/next.js/commit/93cb90891402fa4c47798d03cb9e05c13233766c)
-
[https://github.com/vercel/next.js/releases/tag/v15.5.21](https://redirect.github.com/vercel/next.js/releases/tag/v15.5.21)
-
[https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
-
[https://github.com/advisories/GHSA-q8wf-6r8g-63ch](https://redirect.github.com/advisories/GHSA-q8wf-6r8g-63ch)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-q8wf-6r8g-63ch)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Next.js: Server-Side Request Forgery in rewrites via
attacker-controlled destination hostname
[CVE-2026-64645](https://nvd.nist.gov/vuln/detail/CVE-2026-64645) /
[GHSA-p9j2-gv94-2wf4](https://redirect.github.com/advisories/GHSA-p9j2-gv94-2wf4)

<details>
<summary>More information</summary>

#### Details
##### Impact

A `rewrites()` or `redirects()` rule that builds its external
destination hostname from request-controlled input can be pointed at an
arbitrary hostname, regardless of the rule's hostname suffix. For a
rewrite, Next.js proxies the request to that arbitrary host and serves
the response from the application's origin, leading to Server-Side
Request forgery. A `redirects()` rule configured this way is vulnerable
to an Open Redirect.

This affects any destination that puts a dynamic segment in the
hostname, whether from the path:

```javascript
// next.config.js
module.exports = {
  async rewrites() {
    return [
      {
        source: '/:tenant',
        destination: 'https://:tenant.api.example.com',
      },
    ]
  },
}
```

or from a `has` capture:

```javascript
// next.config.js
module.exports = {
  async rewrites() {
    return [
      {
        source: '/',
        has: [{ type: 'query', key: 'region', value: '(?<region>.+)' }],
        destination: 'https://:region.api.example.com',
      },
    ]
  },
}
```

##### Workarounds

If you cannot upgrade immediately, do not build the hostname of an
external `rewrites()` or `redirects()` destination from user-controlled
input. If a dynamic subdomain is required, constrain the value to
hostname-safe characters: `value: '(?<region>[a-z0-9-]+)'`.

#### Severity
- CVSS Score: 8.3 / 10 (High)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N/SC:L/SI:L/SA:N`

#### References
-
[https://github.com/vercel/next.js/security/advisories/GHSA-p9j2-gv94-2wf4](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-p9j2-gv94-2wf4)
-
[https://github.com/vercel/next.js/commit/35f501357e9b0fe7c950b0d6aa8fcf5343f707e9](https://redirect.github.com/vercel/next.js/commit/35f501357e9b0fe7c950b0d6aa8fcf5343f707e9)
-
[https://github.com/vercel/next.js/commit/d3033266c6dff23f7be71e19341fe3a8c6e2c599](https://redirect.github.com/vercel/next.js/commit/d3033266c6dff23f7be71e19341fe3a8c6e2c599)
-
[https://github.com/vercel/next.js/releases/tag/v15.5.21](https://redirect.github.com/vercel/next.js/releases/tag/v15.5.21)
-
[https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
-
[https://github.com/advisories/GHSA-p9j2-gv94-2wf4](https://redirect.github.com/advisories/GHSA-p9j2-gv94-2wf4)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-p9j2-gv94-2wf4)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Next.js: Unbounded Server Action payload in Edge runtime
[CVE-2026-64646](https://nvd.nist.gov/vuln/detail/CVE-2026-64646) /
[GHSA-4c39-4ccg-62r3](https://redirect.github.com/advisories/GHSA-4c39-4ccg-62r3)

<details>
<summary>More information</summary>

#### Details
##### Impact

Requests targeting Next.js applications using App Router with at least
one Server Action can lead to excessive memory consumption if that
Server Actions uses the Edge runtime

##### Workarounds

If you cannot upgrade, ensure your hosting provider limits the request's
body size. 5 MiB should be allowed at max by your hosting provider.

#### Severity
- CVSS Score: 6.3 / 10 (Medium)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N`

#### References
-
[https://github.com/vercel/next.js/security/advisories/GHSA-4c39-4ccg-62r3](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-4c39-4ccg-62r3)
-
[https://github.com/vercel/next.js/commit/57c31f724d746e86a9e8b92aa8be538a922446a4](https://redirect.github.com/vercel/next.js/commit/57c31f724d746e86a9e8b92aa8be538a922446a4)
-
[https://github.com/vercel/next.js/commit/9a4651e754f70b12e397694ffc41f44c3ba8cc17](https://redirect.github.com/vercel/next.js/commit/9a4651e754f70b12e397694ffc41f44c3ba8cc17)
-
[https://github.com/vercel/next.js/releases/tag/v15.5.21](https://redirect.github.com/vercel/next.js/releases/tag/v15.5.21)
-
[https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
-
[https://github.com/advisories/GHSA-4c39-4ccg-62r3](https://redirect.github.com/advisories/GHSA-4c39-4ccg-62r3)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-4c39-4ccg-62r3)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Next.js: Cache confusion of response bodies for requests with bodies
containing invalid UTF-8 byte sequences
[CVE-2026-64647](https://nvd.nist.gov/vuln/detail/CVE-2026-64647) /
[GHSA-4633-3j49-mh5q](https://redirect.github.com/advisories/GHSA-4633-3j49-mh5q)

<details>
<summary>More information</summary>

#### Details
##### Impact

A server-side `fetch` with a request body may return a cached
**response** body from a different request to the same URL but different
body. Confidential data in the `POST`'s **response** body would then
leak to unauthorized requests. Though the request itself will not be
deduped.

This is only an issue when receiving request bodies with a content type
charset other than UTF-8. For example, the UTF-16 byte sequences for
`삃삃` and `섄섄` in the request body would share the same cache.

##### Workarounds

If you cannot upgrade, consider only making fetch requests with UTF-8
bodies (default in Next.js). Applications using Pages Router are not
vulnerable.

#### Severity
- CVSS Score: 6.3 / 10 (Medium)
- Vector String:
`CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N`

#### References
-
[https://github.com/vercel/next.js/security/advisories/GHSA-4633-3j49-mh5q](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-4633-3j49-mh5q)
-
[https://github.com/vercel/next.js/pull/96008](https://redirect.github.com/vercel/next.js/pull/96008)
-
[https://github.com/vercel/next.js/commit/025bf4a5f7b47fb7758c4ebf1c931a61c451c082](https://redirect.github.com/vercel/next.js/commit/025bf4a5f7b47fb7758c4ebf1c931a61c451c082)
-
[https://github.com/vercel/next.js/releases/tag/v15.5.21](https://redirect.github.com/vercel/next.js/releases/tag/v15.5.21)
-
[https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
-
[https://github.com/advisories/GHSA-4633-3j49-mh5q](https://redirect.github.com/advisories/GHSA-4633-3j49-mh5q)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-4633-3j49-mh5q)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Next.js: Cache confusion of response bodies for requests with bodies
[CVE-2026-64648](https://nvd.nist.gov/vuln/detail/CVE-2026-64648) /
[GHSA-68g3-v927-f742](https://redirect.github.com/advisories/GHSA-68g3-v927-f742)

<details>
<summary>More information</summary>

#### Details
##### Impact

A server-side `fetch` with a request body may return a cached
**response** body from a different request to the same URL but different
body. Confidential data in the `POST`'s **response** body would then
leak to unauthorized requests. Though the request itself will not be
deduped.

This only applies to `fetch` calls with a request that has a different
init than the one passed to `fetch`.
Safe: `fetch(new Request(init), init)`
Unsafe: `fetch(new Request(init), aDifferentInit)`

##### Workarounds

No workaround exists besides upgrading. Applications using Pages Router
are not vulnerable.

#### Severity
- CVSS Score: 6.0 / 10 (Medium)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N`

#### References
-
[https://github.com/vercel/next.js/security/advisories/GHSA-68g3-v927-f742](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-68g3-v927-f742)
-
[https://github.com/vercel/next.js/commit/062f66700b52a5d6bba2c0605d55577ab7ad262c](https://redirect.github.com/vercel/next.js/commit/062f66700b52a5d6bba2c0605d55577ab7ad262c)
-
[https://github.com/vercel/next.js/commit/73b94872bc343d09494b50394d8c08eb9fc8e56a](https://redirect.github.com/vercel/next.js/commit/73b94872bc343d09494b50394d8c08eb9fc8e56a)
-
[https://github.com/vercel/next.js/releases/tag/v15.5.21](https://redirect.github.com/vercel/next.js/releases/tag/v15.5.21)
-
[https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
-
[https://github.com/advisories/GHSA-68g3-v927-f742](https://redirect.github.com/advisories/GHSA-68g3-v927-f742)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-68g3-v927-f742)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Next.js: Server-Side Request Forgery in Server Actions on custom
servers
[CVE-2026-64649](https://nvd.nist.gov/vuln/detail/CVE-2026-64649) /
[GHSA-89xv-2m56-2m9x](https://redirect.github.com/advisories/GHSA-89xv-2m56-2m9x)

<details>
<summary>More information</summary>

#### Details
##### Impact

When a Server Action forwards or redirects a request, an attacker can
cause the server to send that outbound request to a malicious host
(Server-Side Request Forgery). This requires the attacker's request to
control Host-associated headers. In some configurations, it's also
possible to obtain internal values that weaken middleware/proxy
authorization.

Applications that use Server Actions are affected when the incoming host
header is not fixed to a trusted value. This typically occurs on custom
servers, or on deployments not behind a proxy that pins the host.
Managed hosting pins the host upstream and is not affected; `next start`
and standalone output do the same from version 14.2 onward.

##### Workarounds

If you cannot upgrade, ensure clients do not control the host header
your application receives. Pin or validate `Host` and `X-Forwarded-Host`
at your edge or proxy. On version 14.2.0 and later, you can additionally
set the `__NEXT_PRIVATE_ORIGIN` environment variable to your
deployment's real origin:

```bash
__NEXT_PRIVATE_ORIGIN=https://www.example.com node server.js

#### Severity
- CVSS Score: 8.3 / 10 (High)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N`

#### References
- [https://github.com/vercel/next.js/security/advisories/GHSA-89xv-2m56-2m9x](https://redirect.github.com/vercel/next.js/security/advisories/GHSA-89xv-2m56-2m9x)
- [https://github.com/vercel/next.js/commit/b51206321854193208c0805ba42acc49287f942b](https://redirect.github.com/vercel/next.js/commit/b51206321854193208c0805ba42acc49287f942b)
- [https://github.com/vercel/next.js/commit/e3e5666ccead3a15162793d697af5e48b7cc0498](https://redirect.github.com/vercel/next.js/commit/e3e5666ccead3a15162793d697af5e48b7cc0498)
- [https://github.com/vercel/next.js/releases/tag/v15.5.21](https://redirect.github.com/vercel/next.js/releases/tag/v15.5.21)
- [https://github.com/vercel/next.js/releases/tag/v16.2.11](https://redirect.github.com/vercel/next.js/releases/tag/v16.2.11)
- [https://github.com/advisories/GHSA-89xv-2m56-2m9x](https://redirect.github.com/advisories/GHSA-89xv-2m56-2m9x)

This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-89xv-2m56-2m9x) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Release Notes

<details>
<summary>vercel/next.js (next)</summary>

### [`v16.2.11`](https://redirect.github.com/vercel/next.js/compare/v16.2.10...v16.2.11)

[Compare Source](https://redirect.github.com/vercel/next.js/compare/v16.2.10...v16.2.11)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/vivid-planet/dextinity).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC40OS4wIiwidXBkYXRlZEluVmVyIjoiNDQuNDkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
## Problem

`FormMutation` is exported from `@dextinity/admin`, but rendering it
always fails:

> TypeError: Cannot read properties of undefined (reading 'props')

Nothing uses it. Not in this repository and not in any of our client
projects, where a search turns up only unrelated GraphQL operation
constants whose names happen to end in `FormMutation`.

## Cause

It reads its children from `this.props` although it is a function
component. Modules are always in strict mode, so `this` is `undefined`
when React calls the component.

## Fix

Read from `props` instead.

## Decisions

- **Fixed rather than removed, even though nothing uses it.** Deleting
it is the obvious alternative, but removing a published export is a
breaking change and would have to target `next`.

## Verification

Added `FormMutation.test.tsx`, which renders the component and asserts
that its children receive the mutation actions and the combined loading
and error state. Putting `this.` back in front of `props.children` makes
it fail.

Comparing all 343 emitted `.d.ts` files against `main` shows one further
change: `FormMutation`'s inferred return type goes from `any` to
`ReactNode`. On `main`, `noImplicitThis` is off, so `this` was
implicitly `any` and made `this.props.children(...)` — and with it the
component — `any`. Reading from `props` yields the `ReactNode` that
`IProps.children` declares. Narrowing away an `any` can break a call
site in principle, but the component throws unconditionally today, so
there is no working call site to break.

## Further information

- Found while enabling TypeScript's `strict` mode, where
`noImplicitThis` flagged it:
[COM-1079](https://vivid-planet.atlassian.net/browse/COM-1079). It
stands on its own as a bugfix, and is a prerequisite for the `admin`
step of that chain.


[COM-1079]:
``https://vivid-planet.atlassian.net/browse/COM-1079?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ``

---------

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

Some mail clients, such as GMX and Web.de, do not apply the `<style>`
block in the head.

MJML keeps the real column widths only there, in a `min-width` media
query, and writes `width: 100%` inline instead.
Every multi-column example therefore rendered as a stack in those
clients, with the inner-edge gap padding left behind as an indent on the
second column.

The examples with that `<style>` block removed:

| Before | After |
| --- | --- |
| <img width="380" alt="before-two-column"
src="https://github.com/user-attachments/assets/22afc9cf-f2e0-4f3a-bd40-75ed9e35b0e8"
/> | <img width="380" alt="after-two-column"
src="https://github.com/user-attachments/assets/9d51434e-7fee-4ef8-a5a7-cb83d1303a71"
/> |
| <img width="380" alt="before-three-column"
src="https://github.com/user-attachments/assets/b54b345e-404f-4a3f-b198-5ab8d185e3c7"
/> | <img width="380" alt="after-three-column"
src="https://github.com/user-attachments/assets/62a41187-db8f-4037-96d9-a1496f8ac87f"
/> |
| <img width="380" alt="before-asymmetric"
src="https://github.com/user-attachments/assets/db58e185-5063-4a60-842b-29455f9084c8"
/> | <img width="380" alt="after-asymmetric"
src="https://github.com/user-attachments/assets/56f9e5b4-7e53-45d3-a5f6-5be40b3a7bdd"
/> |

---

Task: https://vivid-planet.atlassian.net/browse/PHSB2C-13730

---------

Co-authored-by: Ricky Smith <jamesricky@me.com>
The Storybook in `storybook/` composes the mail Storybook.
Composition loads only the preview of a referenced Storybook, not its
manager, so the addon's toolbar buttons and the MJML warnings panel were
missing from the mail stories shown there.

Co-authored-by: Ricky Smith <jamesricky@me.com>
…6276)

## Problem

In a project whose block form sits inside a `SaveBoundary`, hovering a
block in the block preview does not mark the block's entry in the block
list, and hovering a list entry does not mark the block in the preview.
Both directions fail silently.

`HoverPreviewComponent` builds the block's route from
`useRouteMatch().url`. The routes of the previewed blocks are built from
a different base: `createBlocksBlock`, `createListBlock` and
`createColumnsBlock` use `previewCtx.parentUrlSubRoute ??
previewCtx.parentUrl`, and `createCompositeBlock` sets
`parentUrlSubRoute` exactly where it renders child blocks inside a
`SubRoute`.

A `SubRoute` passes its path through a React context, not a router
match, so `useRouteMatch` cannot see it. `SaveBoundary` renders a
`RouterPrompt` with `subRoutePath: "./save"` by default, so in any
project that passes `parentUrl: useSubRoutePrefix()` the two routes
differ by that one segment and
`hoveredSiteRoute?.includes(componentRoute)` never matches.

Measured in such a project (article editor, 12 blocks):

Preview -> admin, on hovering a block in the preview:

```json
{ "cometType": "HoverComponent", "data": { "route": ".../edit/save/<blockKey>/blocks" } }
```

Admin -> preview, on hovering a list entry:

```json
{ "cometType": "HoverComponent", "data": { "adminRoute": ".../edit/<blockKey>/blocks" } }
```

Injecting a `HoverComponent` message into the admin by hand confirms it:
the route without `save` marks the matching list entry, the route with
`save` marks nothing.

Clicking a block is not affected. `SelectPreviewComponent` sends
`location.pathname` and `IFrameBridgeProvider` navigates with
`history.push(message.data.adminRoute)`, so both use the full route
including the sub-route segment.

## Solution

Build the route from `useSubRoutePrefix`, the prefix the block routes in
`BlockPreviewContext` already use.

```diff
+import { useSubRoutePrefix } from "@dextinity/admin";
 import { type PropsWithChildren, useEffect, useRef } from "react";
-import { useRouteMatch } from "react-router";

-    const match = useRouteMatch();
+    const subRoutePrefix = useSubRoutePrefix();

-    const componentRoute = componentSlug.startsWith("#") ? `${match.url}${componentSlug}` : `${match.url}/${componentSlug}`;
+    const componentRoute = componentSlug.startsWith("#") ? `${subRoutePrefix}${componentSlug}` : `${subRoutePrefix}/${componentSlug}`;
```

This is safe in the other two cases: `useSubRoutePrefix()` returns
`match.url` as soon as that starts with the `SubRoute` path, so nested
blocks — where `match.url` is the real URL — keep the route they have
today. Without a `SubRoute` it returns `match.url` unchanged, so the
demo and the starter behave exactly as before.

## Further information

The bug is only reproducible in a project that combines a `SaveBoundary`
with `parentUrl: useSubRoutePrefix()`; neither the demo nor the starter
does, which is why it went unnoticed.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vivid-planet-bot vivid-planet-bot changed the title Merge main into next [Conflicts] Merge main into next Sep 1, 2026
…sers list (#6279)

## Problem

The user permissions users list rendered a "Permissions" and a "Scopes"
column for every user. Both required resolving per-user data for every
row — a permission count and a content scope count computed through a
dedicated request-scoped DataLoader. That added meaningful complexity
(an extra service and two resolve fields) and per-row cost for
information that is already available in more detail on the user's edit
page.

Additionally, the `contentScopesCount` counts a wildcard content scope
(`"*"`) as a single scope and therefore under-reports the number of
scopes a user can actually access.

## Solution

Remove both columns and the machinery behind them. The users list now
shows the name, the email and the row actions.

- Remove the two columns and the
`UserAvailablePermissionsAndContentScopes` query from
`UserPermissionsUserGrid`, and drop
`permissionsCount`/`contentScopesCount` from the `UserForGrid` fragment.
- Deprecate the `permissionsCount` and `contentScopesCount` fields of
`UserPermissionsUser` and return `0` instead of removing them, so
existing consumers (mocks, generated types in projects) keep working.
They will be removed in the next major version.
- Remove the `UserContentScopesLoaderService` and
`UserPermissionsService.getContentScopesForUsers()`, which only existed
to serve the `contentScopesCount` field resolver.

## Example

The users list in Demo Admin now renders name, email and the row actions
only.

## Further information

This is a port of #6135 to `main`. That pull request is layer 2 of a
stacked pull request and targets
`claude/user-permissions-content-scope-wildcard` (#6114); this one
contains the same change based on `main`, so it can be merged (and
backported) independently of the rest of the stack. The
deprecate-instead-of-remove approach follows the review feedback on
#6135.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
…items (#6281)

## Summary
- Superscript, Subscript, and custom inline-style menu items in the
TipTap toolbar's "More options" menu placed their icon directly after
the label using a custom flexbox layout, so the icon's horizontal
position varied with the label's length.
- They now use MUI's `ListItemIcon`/`ListItemText` with the icon leading
the label, matching MUI's own menu item convention.

Follow-up requested by @nsams on #6246 (comment:
#6246 (comment)).

Stacked on #6246 — targets that branch instead of `main` so it merges
after it.

Before:
<img width="377" height="315" alt="Bildschirmfoto 2026-08-27 um 13 32
12"
src="https://github.com/user-attachments/assets/b56447b8-758a-499e-9f52-e9dee85395a6"
/>

After:
<img width="319" height="212" alt="Bildschirmfoto 2026-09-01 um 10 56
10"
src="https://github.com/user-attachments/assets/43e5b690-59bc-4aeb-a8e4-742dba4e73ce"
/>

Storybook:
https://deploy-preview-6281.cms-storybook.dextinity.com/?path=/story/@dextinity/cms-admin_blocks-tiptaprichtextblock--combined-text-block-and-inline-styles

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
## Summary
Updated `.gitignore` to exclude the `.playwright-cli/` directory from
version control.

## Changes
- Added `.playwright-cli/` entry to `.gitignore` to prevent CLI-related
artifacts from being tracked in the repository

## Details
This follows the existing pattern of excluding other Playwright-related
directories (`.playwright` and `.playwright-mcp`) that are generated
during local development and testing.

https://claude.ai/code/session_0137NeuvLqaDV1UcAMW29qMq

Co-authored-by: Claude <noreply@anthropic.com>
Disable the features because we don't use GitHub issues and CodeRabbit
has no access to Jira (for now).

https://claude.ai/code/session_01EqUf9DSdq63m9FJGpWr9fC

---------

Co-authored-by: Claude <noreply@anthropic.com>
Add "coderabbit config" to avoid auto approving changes to the requires
human review rule.

(and convert to list for easier editing)
Percentage columns would have removed the `calc()` altogether, but they
let the narrow column shrink below `bodyWidth`, so the layout would
change in every client instead of only in the ones with the defect.

---

Task: https://vivid-planet.atlassian.net/browse/PHSB2C-13730

Co-authored-by: Ricky Smith <jamesricky@me.com>
…6316)

Outlook.com and the Outlook apps for iOS and Android drop everything
that follows the first `}}` of a `<style>` tag.
Minified CSS ends every `@media` block with `}}`, so these clients
applied the rules of the first block only and used the desktop layout
for everything after it.

See hteumeuleu/email-bugs#92


| Client | Before fix | After fix |
|--------|--------|--------|
| Outlook iOS 26 | <img width="645" height="730" alt="Outlook iOS 26
Before"
src="https://github.com/user-attachments/assets/aee50844-2d0e-4064-bf27-7d329d8eaa40"
/> | <img width="645" height="730" alt="Outlook iOS 26 After"
src="https://github.com/user-attachments/assets/33192f58-6b89-42f2-a43e-650006300e00"
/> |
| Outlook Web | <img width="390" height="562" alt="Outlook Web Before"
src="https://github.com/user-attachments/assets/8e41550c-be4c-4f85-9fd3-0787de072e32"
/> | <img width="390" height="562" alt="Outlook Web Now"
src="https://github.com/user-attachments/assets/c94f67dd-5ba2-4c1a-b8a6-cb91d69561a4"
/> |

---

https://vivid-planet.atlassian.net/browse/PHSB2C-13931

---------

Co-authored-by: Ricky Smith <jamesricky@me.com>
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @dextinity/cms-admin@10.4.0

### Minor Changes

-   4b9ead5: Add `icon` option to `TipTapInlineStyle`

Custom inline styles shown in the rich text toolbar's "More options"
menu can now specify an `icon`, displayed next to the label the same way
Superscript/Subscript already are:

    ```tsx
    createTipTapRichTextBlock({
        inlineStyles: [
            {
                name: "highlight",
label: <FormattedMessage id="..." defaultMessage="Highlight" />,
                icon: RteHighlight,
element: (props) => <span style={{ backgroundColor: "#fff3cd" }}
{...props} />,
            },
        ],
    });
    ```

`icon` is optional; menu items without one keep rendering as before.

- 4b9ead5: Move custom TipTap inline styles into the toolbar's "More
options" menu

Custom `inlineStyles` (e.g. a project-specific "Uppercase" style) used
to render as their own always-visible dropdown in the rich text toolbar.
They now appear as toggleable menu items inside the "More options"
("...") menu, next to Superscript/Subscript, matching how the previous
Draft.js-based rich text editor exposed custom inline styles as toolbar
toggles rather than a separate dropdown.

- a00f0b2: Support wildcard values for content scope dimensions in
`getContentScopesForUser`

`getContentScopesForUser` can now use the wildcard value `"*"` as the
value of a content scope dimension to grant access to any value for that
dimension. The wildcard is matched during the content scope check, so it
does not need to be part of `availableContentScopes`.

      **Example**

    ```ts
    getContentScopesForUser(user: User): ContentScopesForUser {
        // Grant access to every language within the "main" domain
        return [{ domain: "main", language: "*" }];
    }
    ```

For users with access to all content scopes,
`currentUser.permissions[].contentScopes` now returns a single wildcard
scope (e.g. `[{ domain: "*", language: "*" }]`) instead of the
enumerated `availableContentScopes`. The default `isAllowed` and
`currentUser.allowedContentScopes` handle the wildcard; a custom
`isAllowed` must treat `"*"` as matching any value of a dimension.

### Patch Changes

- b6cbbd9: Move icons to the start of the TipTap "More options" menu
items

Superscript, Subscript, and custom inline-style menu items placed their
icon directly after the label using a custom flexbox layout, so the
icon's horizontal position varied with the label's length. They now use
MUI's `ListItemIcon`/`ListItemText` with the icon leading the label,
matching MUI's own menu item convention.

    -   @dextinity/admin@10.4.0
    -   @dextinity/admin-date-time@10.4.0
    -   @dextinity/admin-icons@10.4.0
    -   @dextinity/admin-rte@10.4.0

## @dextinity/cms-api@10.4.0

### Minor Changes

- a00f0b2: Support wildcard values for content scope dimensions in
`getContentScopesForUser`

`getContentScopesForUser` can now use the wildcard value `"*"` as the
value of a content scope dimension to grant access to any value for that
dimension. The wildcard is matched during the content scope check, so it
does not need to be part of `availableContentScopes`.

      **Example**

    ```ts
    getContentScopesForUser(user: User): ContentScopesForUser {
        // Grant access to every language within the "main" domain
        return [{ domain: "main", language: "*" }];
    }
    ```

For users with access to all content scopes,
`currentUser.permissions[].contentScopes` now returns a single wildcard
scope (e.g. `[{ domain: "*", language: "*" }]`) instead of the
enumerated `availableContentScopes`. The default `isAllowed` and
`currentUser.allowedContentScopes` handle the wildcard; a custom
`isAllowed` must treat `"*"` as matching any value of a dimension.

## @dextinity/admin@10.4.0

### Patch Changes

-   @dextinity/admin-icons@10.4.0

## @dextinity/admin-color-picker@10.4.0

### Patch Changes

-   @dextinity/admin@10.4.0
-   @dextinity/admin-icons@10.4.0

## @dextinity/admin-date-time@10.4.0

### Patch Changes

-   @dextinity/admin@10.4.0
-   @dextinity/admin-icons@10.4.0

## @dextinity/admin-generator@10.4.0

### Patch Changes

-   Updated dependencies [4b9ead5]
-   Updated dependencies [4b9ead5]
-   Updated dependencies [b6cbbd9]
-   Updated dependencies [a00f0b2]
    -   @dextinity/cms-admin@10.4.0
    -   @dextinity/admin@10.4.0
    -   @dextinity/admin-icons@10.4.0

## @dextinity/admin-rte@10.4.0

### Patch Changes

-   @dextinity/admin@10.4.0
-   @dextinity/admin-icons@10.4.0

## @dextinity/brevo-admin@10.4.0

### Patch Changes

-   Updated dependencies [4b9ead5]
-   Updated dependencies [4b9ead5]
-   Updated dependencies [b6cbbd9]
-   Updated dependencies [a00f0b2]
    -   @dextinity/cms-admin@10.4.0
    -   @dextinity/admin@10.4.0
    -   @dextinity/admin-date-time@10.4.0
    -   @dextinity/admin-icons@10.4.0

## @dextinity/api-generator@10.4.0

### Patch Changes

-   Updated dependencies [a00f0b2]
    -   @dextinity/cms-api@10.4.0

## @dextinity/brevo-api@10.4.0

### Patch Changes

-   Updated dependencies [a00f0b2]
    -   @dextinity/cms-api@10.4.0

## @dextinity/eslint-config@10.4.0

### Patch Changes

-   @dextinity/eslint-plugin@10.4.0

## @dextinity/mail-react@10.4.0

### Patch Changes

- 98c1097: Fix head CSS lost after the first `@media` block in
Outlook.com and the Outlook apps for iOS and Android

These clients stop reading a `<style>` tag at the first `}}`, which
minified CSS writes at the end of every `@media` block.

- bb5d22a: Apply the Storybook addon's **"Use public image URLs"**
toggle to the Outlook VML image source

- 583dd13: Fix `borderRadius` on images in classic Outlook, which
rounded corners twice as much as the value asked for

## @dextinity/site-nextjs@10.4.0

### Patch Changes

-   Updated dependencies [0e88bab]
    -   @dextinity/site-react@10.4.0

## @dextinity/site-react@10.4.0

### Patch Changes

- 0e88bab: Fix block preview outlines being cut off when
`IFrameBridgeProvider` does not start at the left edge of the page, for
instance because of padding or centering

## @dextinity/admin-babel-preset@10.4.0



## @dextinity/admin-icons@10.4.0



## @dextinity/agent-features@10.4.0



## @dextinity/cli@10.4.0



## @dextinity/eslint-plugin@10.4.0

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Problem

Content scope dimensions were only known implicitly from the keys of the
`availableContentScopes` values. An optional dimension that is not part
of `availableContentScopes` (e.g. one with too many values to enumerate)
therefore had no runtime representation at all — it could neither be
declared nor used with arbitrary values.

## Solution

Add an optional `availableContentScopeDimensions` option to the
`UserPermissionsModule` to declare the content scope dimensions (with
optional labels) at runtime. When omitted, the dimensions are derived
from the keys of `availableContentScopes` as before, so existing apps
are unaffected. The declared dimensions are used to represent access to
all content scopes as a per-dimension wildcard (`{ domain: "*", ... }`),
which therefore also covers dimensions that are not part of
`availableContentScopes`.

A content scope for a dimension that is not part of
`availableContentScopes` may now hold any value (including the `"*"`
wildcard).

### Removing `checkContentScopes`

Content scopes are no longer validated against `availableContentScopes`
(the `checkContentScopes` method is removed), because:

- **It was not the authorization boundary.** Access is enforced per
request by `isAllowed` / `isScopeWithin`, which compares the requested
resource's scope against the user's granted scopes and never consults
`availableContentScopes`. A stale content scope (e.g. one pointing at a
removed domain) matches no real resource, so it cannot cause an
over-grant.
- **It gave no durable guarantee.** `availableContentScopes` can be
resolved dynamically (a factory), so validating at write time says
nothing about validity later: a scope valid when saved can become
invalid after a config change, and vice versa.
- **It became incoherent.** With dimensions that can live outside
`availableContentScopes` and hold any value (including `"*"`),
`availableContentScopes` no longer describes the full space of valid
content scopes, so matching against it would reject legitimate scopes.

## Example

```ts
UserPermissionsModule.forRootAsync({
    useFactory: () => ({
        availableContentScopes: [ ... ],
        availableContentScopeDimensions: [{ name: "domain", label: "Domain (Website)" }, { name: "language" }, { name: "product" }],
        // ...
    }),
    // ...
});
```

## Stacked pull request

This is layer 2 of 3 of a stacked pull request. Review and merge
bottom-up (each layer targets the one above it):

1. Support wildcard values for content scope dimensions → `main` (#6114)
2. **Allow declaring content scope dimensions at runtime** (this PR) →
#6114 (#6115)
3. Rework content scopes management in the user permissions panel →
#6115 (#6116)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

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

## Summary
Replaced the `axios` HTTP client with the native `fetch` API for
requesting email campaign content from the frontend service. This
eliminates the dependency on `@nestjs/axios` and `axios` packages.


https://claude.ai/code/session_019JWn9RfULGPQpbCLn9M1k5

Co-authored-by: Claude <noreply@anthropic.com>
## Description

`PageTreeNodeScope`/`PageTreeNodeScopeInput` are the fixed GraphQL type
names a project-specific `PageTreeNode` scope class must use — a comment
in `demo/api/src/page-tree/dto/page-tree-node-scope.ts` even calls this
out ("name must not be changed in the app"). Nothing enforced it though,
so an accidental rename would only surface later as a confusing runtime
GraphQL schema error, instead of failing fast with a clear message.

`DamModule` already has this exact safeguard for its own `Scope` option
(validating against `"DamScope"`/`"DamScopeInput"`). This PR adds the
equivalent check to `PageTreeModule.forRoot()`.

## Solution

In `packages/api/cms-api/src/page-tree/page-tree.module.ts`, after
resolver generation (so the input type metadata is available) and before
building providers, validate that a provided `Scope` class is decorated
with `@ObjectType("PageTreeNodeScope")` and
`@InputType("PageTreeNodeScopeInput")` via `TypeMetadataStorage`,
throwing a descriptive error otherwise — mirroring
`DamModule.register()`.

## Example usage

If a project's custom scope class is decorated with the wrong GraphQL
type name, e.g.:

```ts
@ObjectType("MyScope") // wrong, should be "PageTreeNodeScope"
@inputType("MyScopeInput")
export class MyPageTreeNodeScope { ... }
```

`PageTreeModule.forRoot({ Scope: MyPageTreeNodeScope, ... })` now throws
at startup:

```
Error: Invalid object type name for provided page tree scope class. Make sure to decorate the class with @ObjectType("PageTreeNodeScope")
```

instead of failing later with an opaque GraphQL schema error.

## Further information

- No existing tests cover `DamModule`'s equivalent validation, so no new
test was added here either, to stay consistent.
- Closes #6172

---
Generated by [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
#6173 still had the old
package name.

https://claude.ai/code/session_01WcusBvi4DqA9ywA3U3mBBP

Co-authored-by: Claude <noreply@anthropic.com>
… per feature (#6311)

`createTipTapRichTextBlock` now takes a single root options object with
one option per editor feature, similar to TipTap's `StarterKit`
configuration. Feature-specific options move into a nested options
object of the feature they belong to, so `headingLevels` becomes
`heading: { levels: [...] }`.

Every feature is enabled by default (except `underline`) and is disabled
by passing `false`, so a configuration only has to state what deviates
from the defaults instead of repeating every supported feature. Links
stay the exception: they are enabled by passing the link block as
`link`.

**Example**

```ts
// Before
createTipTapRichTextBlock({
    supports: ["bold", "italic", "strike", "sub", "sup", "heading", "ordered-list", "unordered-list"],
    headingLevels: [2, 3],
});

// After
createTipTapRichTextBlock({
    nonBreakingSpace: false,
    softHyphen: false,
    heading: { levels: [2, 3] },
});
```

The features are named after their option: `bold`, `italic`,
`underline`, `strike`, `sub`, `sup`, `heading`, `orderedList`,
`unorderedList`, `nonBreakingSpace`, `softHyphen`, `link`, and `history`
(Admin only). The document-level limits `maxTextBlocks` and
`listLevelMax` are unchanged.

https://claude.ai/code/session_01DSMzvHiJUJT1RneuXcGmRV

---------

Co-authored-by: Claude <noreply@anthropic.com>
Outlook renders the shape one pixel wider and taller than the size it is
given, so it is given one pixel less. The extra pixel appears to be the
shape's stroke, which defaults to one pixel and sits outside the
declared size; switching the stroke off does not release it.

| Before (Outlook Office 365 Windows 10) | Now (Outlook Office 365
Windows 10) |
|--------|--------|
| <img width="630" height="1265" alt="1px bug before"
src="https://github.com/user-attachments/assets/22613da7-8a09-495c-a486-af9495db785e"
/> | <img width="630" height="1265" alt="1px bug after"
src="https://github.com/user-attachments/assets/f535e259-f538-4062-804c-4d5d8e20fa1e"
/> |

---

Task: https://vivid-planet.atlassian.net/browse/PHSB2C-13931

Co-authored-by: Ricky Smith <jamesricky@me.com>
VPS-Ricky and others added 2 commits September 7, 2026 16:00
"Behavior" on its own read as any behavior change, so an internal fix
drew a review comment asking for docs it did not need:
#6323 (comment)

Co-authored-by: Ricky Smith <jamesricky@me.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.

10 participants