fix(core): reject taxonomy and menu translations under a different name - #3101
fix(core): reject taxonomy and menu translations under a different name#3101danielmlr wants to merge 1 commit into
Conversation
Creating a taxonomy or a menu with `translationOf` accepted any `name`, so the new row could join the source's translation group under a second name. Both are looked up by name and locale, so the source's name never returned that translation in its locale. The two create handlers now return VALIDATION_ERROR when the names differ. The REST routes and the MCP `taxonomy_create` and `menu_create` tools go through them; the menu translations route already passes the source's name.
🦋 Changeset detectedLatest commit: 6187ea5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 18 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-test
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/registry-moderation
@emdash-cms/registry-verification
@emdash-cms/sandbox-workerd
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
There was a problem hiding this comment.
This is the right fix for the translation-name issue described in #2525. Menus and taxonomy definitions are resolved by (name, locale), so a translation created under a different name joins the source's translation group but is invisible to lookups that use the source name. Rejecting the mismatch at the create handlers is the correct place: both the REST POST routes and the MCP taxonomy_create/menu_create tools call these handlers, and the dedicated menu translations route already passes the source's name.
The implementation is small and safe: the name check runs after the source-existence check and before any duplicate guard or DB write, so a mismatched-name request returns VALIDATION_ERROR without persisting anything. The input schemas and the repository layer remain unchanged except for the new validation, which is fine because the handlers are the API boundary. The new tests verify the actual failure (wrong name → VALIDATION_ERROR plus no row created) rather than asserting the implementation back at itself, and existing translation-success tests still pass with matching names. The changeset accurately describes the user-facing behavior.
I checked the changed handlers, the menu translation route, the MCP tool definitions, the input schemas, the repository implementations, and the updated tests. No logic bugs, no authorization/locale-filter/SQL issues, and nothing on the logged-out hot path. The only optional improvement would be surfacing the name-must-match constraint in the MCP tool descriptions and the OpenAPI taxonomy translations description, but that's a documentation completeness note, not a blocker.
What does this PR do?
Rejects a taxonomy or menu translation created under a different name than its source. Creating either with
translationOfaccepted anyname, so the new row joined the source's translation group under a second name. Both resolve by name and locale, so a lookup by the source's name in that locale never returned the translation.The create handlers now return
VALIDATION_ERRORwhen the names differ. The REST routes and the MCPtaxonomy_createandmenu_createtools use them; the menu translations route already passes the source's name. Explicithierarchicalandcollectionson a taxonomy translation still apply as given, and seed application is unchanged.Part of #2525
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runmessages.pochanges except in translation PRs — a workflow extracts catalogs on merge tomain. (n/a: no admin UI change)AI-generated code disclosure
Screenshots / test output
Not applicable for screenshots.
mainand pass here on SQLite; CI also runs the taxonomy case on Postgres.pnpm testinpackages/core→ 553 test files passed, 2 skipped; 6788 tests passed, 10 skipped