Document, element, and media types share the same alias namespace
across content/media (a doc-type and a media-type can use the same
alias), so a "{Schema}PropertiesModel" naming scheme could collide.
Properties model schemas now follow the same Content/Element/Media
suffix as their parent *Model schema:
- Document type: ArticlePageContentPropertiesModel
- Element type: TestElementElementPropertiesModel
- Media type: VideoMediaPropertiesModel
Composition references look up each composition's own IsElement so
that a doc-type composing an element-type (allowed in the UI) still
references the correct ElementPropertiesModel schema.
Replaces the legacy ModelsBuilder-style ToCleanString tokenizer with
ToFirstUpperInvariant. The tokenizer split aliases on case boundaries
and mangled capital-letter runs (e.g. "xMLSitemap" -> "XMlsitemap"),
making the typed schema names harder to read for OpenAPI consumers.
Since content type aliases are already valid identifiers, only the
first character needs uppercasing.
Also adds an "xMLSitemap" sample type to the integration tests to
cover the casing-preservation behavior.
JSON Schema 2020-12 (mandated by OpenAPI 3.1) does not let additionalProperties look through allOf, so a strict validator rejects every inherited field on the composed *ResponseModel/*Model/*PropertiesModel schemas. Most code generators silently ignore it, but the document is technically invalid and the constraint would be a lie anyway since Umbraco can grow new properties in non-major releases.
Removed from all four schema construction sites (response, content type, properties, and the interface-based fallback) and regenerated the affected snapshots.
* Management API sweep
* Remove leftover comment from ContentService
* Clarify TODOs
* Use IPublishedElementCache instead of IElementCacheService in ElementPickerValueConverter
* Rename private helper for clarification
* Fix build error
* Remove "Create" from ElementService, as it was only ever used for tests
* Rename DocumentVariantStateModel to PublishableVariantStateModel in backoffice client
Refresh OpenApi.json and regenerate backend-api after the server-side enum rename, then update all client imports and usages to match.
* Client: Aliased `PublishableVariantStateModel` for each module package
* Client: Resolve circular dependencies for variant-state alias
Hoist the `UmbDocumentVariantState` and `UmbElementVariantState` aliases (re-exporting `PublishableVariantStateModel`) into dedicated `variant-state.ts` files. Internal modules now import the alias from this leaf file instead of the package's root `index.js`, breaking the 5 cycles reported by `npm run check:circular` while keeping the public API surface unchanged.
* Post-merge fixes
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
Co-authored-by: leekelleher <leekelleher@gmail.com>
* Updated webhook tests since Change the default payload type to "minimal"
* Added .skip tag for block grid area tests due to the actual issues
* Update template tests due to test helpers changes
* Updated locator for rollback button due to UI changes
* Updated locator for block edit button due to UI changes
* Updated locator for delete block icon
---------
Co-authored-by: Andreas Zerbst <73799582+andr317c@users.noreply.github.com>
* Delivery API: Drop $type discriminator from response payloads
Removed [JsonDerivedType] from IApiContent and IApiContentResponse so
System.Text.Json stops emitting $type on collection endpoints and the
OpenAPI spec stops requiring a discriminator on the generic schemas,
restoring v17 behaviour. Consumers that need polymorphic responses can
still register derived types via ContentJsonTypeResolverBase.
Snapshot regenerated.
* Delivery API: Preserve cultures property order on collection responses
Added [JsonPropertyOrder(100)] to IApiContentResponse.Cultures so the
property is serialized last when the static type is the interface
(collection endpoints), matching the existing attribute on the concrete
ApiContentResponse class. Mirrors the [JsonPropertyOrder(-100)] pattern
already used for ContentType on IApiElement / ApiElement.
Snapshot regenerated.
* Remove unused obseleted InstalledPackage mapping
* Fix up XML header documentation on PackageViewModelMapDefinition.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Backoffice Element Search: add global search provider for elements
Adds an "Elements" category to the backoffice global search, scoped to
the Library section.
Server: SearchElementItemController exposes
GET /umbraco/management/api/v1/item/element/search
backed by IEntitySearchService (DB-backed name match, mirrors the
DataType search pattern). Maps results via IElementPresentationFactory.
Client: new src/packages/elements/search/ module with a search provider,
repository, server data source, search-result-item element, and
globalSearch manifest (alias Umb.GlobalSearch.Element). Wired into the
elements package manifests. Backend SDK regenerated from OpenApi.json.
* Backoffice Element Search: surface ancestors, trashed and draft state
- New ancestors endpoint at /item/element/ancestors so result items can
render a parent breadcrumb (uses NamedItemResponseModel to cover
element folder ancestors).
- ElementItemResponseModel.IsTrashed added and populated by the
presentation factory, flowing through search and item responses.
- Frontend search result item renders breadcrumb, Trashed tag with
strike-through, and Draft tag (mirrors document search result item).
* Address PR review feedback
- Add integration test for AncestorsElementItemController (mirrors
AncestorsDocumentItemControllerTests).
- UmbElementSearchItemModel: declare `name: string` (the search result
contract requires it; mirrors UmbDocumentSearchItemModel).
- Element search data source: drop the empty-string fallback on `name`
and add the same TODO comment used in the document data source.
- Add JSDoc to UmbElementSearchProvider, UmbElementSearchRepository and
UmbElementSearchServerDataSource (matches document equivalents).
* Backoffice Element Search: export search consts and unblock isTrashed on item endpoint
- Re-export ./search/constants.js from the elements package barrel so
UMB_ELEMENT_SEARCH_PROVIDER_ALIAS and UMB_ELEMENT_GLOBAL_SEARCH_ALIAS
are reachable as the export-consts test expects.
- element-item.server.data-source.ts: stop hardcoding isTrashed to false
- now that ElementItemResponseModel exposes the flag, item-based UIs
reflect the actual trashed state.
* Fix naming warning in UmbracoIntegrationTestBase.
* Fixes a namespace.
* Removed TODO for removing registrations of UserPasswordConfigurationSettings and MemberPasswordConfigurationSettings. The inheritance hierarchy of UmbracoUserManager makes this difficult and unnecessary to unpick.
* Aligned TODO with obsoletion message.
* Remove obsoleted code from IDomainService and update all callers.
* Removed obsolete members from IContentTypeBaseService.
* Addressed code review feedback.
* Fix Setup on ThreadSafetyTests.
* Remove obsolete methods from IDataTypeService and update callers.
* Fixed failing integration test and resolved code review feedback.
* Further code review feedback.
* Introduce shared helper for retrieving data type from property type.
* Change AddElements to a premigration
* Move AddAllowedInLibraryToContentType to premigration
* Remove old migrations and remove obsoleted migratiobase
Includes updating existing migrations and tests to AsyncMigrationBase
* Update claude files
* update xml comment
* Set correct initalstate
* More cleanup
* Remove old migration tests
* Put the test ignore on the right testcase 🙈
* cleanup async migrateasync calls without awaits in tests
* Updated InitialStateVersion
* Refactor element tree controllers to use start node filter service
Move user start node filtering logic from UserStartNodeFolderTreeControllerBase
and ElementTreeControllerBase into a dedicated ElementStartNodeTreeFilterService,
matching the pattern established for document and media trees in PR #22486.
Add a virtual TreeObjectTypes property to UserStartNodeTreeFilterService so
element trees can query both Element and ElementContainer object types.
* Address PR review feedback
* Apply PR review feedback
Replace TreeObjectType (singular) with abstract TreeObjectTypes (array).
Use static readonly arrays in concrete implementations to avoid
allocations.
Move multi-object-type test into UserStartNodeTreeFilterServiceTests
since it exercises base class behavior, not the element service
specifically.
Removes the [JsonDerivedType] attributes from IApiContent,
IApiContentResponse, and IApiElement. Without them System.Text.Json
configures no polymorphism by default, so wire payloads stop carrying
$type fields and the OpenAPI spec stops emitting a discriminator on
the generic schemas - matching v17 Delivery API behaviour. Consumers
that need polymorphic serialization can still register derived types
via ContentJsonTypeResolverBase.
Snapshots regenerated.
The manual approval gates added for the duplicate-version rerun were
single-use scaffolding for that specific release. Remove them and
tighten Deploy_Npm and Upload_API_Docs to require Deploy_NuGet to
have actually succeeded (Succeeded or SucceededWithIssues) — so a
NuGet failure deliberately blocks the npm release and docs upload.
Keep the structural change to inspect dependencies.Deploy_NuGet.result
directly rather than rely on the transitive succeeded(). That fix is
permanent: it's what protects npm and docs from cascade-skipping
whenever MyGet has another upstream outage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ContentJsonTypeResolverBase.GetDerivedTypes goes back to returning
empty. Previously it registered ApiMediaWithCrops and
ApiMediaWithCropsResponse as derived types of their interfaces, which
made every consumer of the resolver (the Delivery API and webhooks)
emit a $type discriminator on media payloads, even when the typed
schema feature was disabled.
The Delivery API still needs a base schema for the typed media
schemas to extend via allOf. Since the concrete media classes are
internal to Umbraco.Infrastructure and cannot be referenced from
[JsonDerivedType] in Core, ContentTypeSchemaTransformer now builds
that base from the interface's own properties when the interface has
no [JsonDerivedType] entries. Content/element interfaces are
unaffected and keep using their declared concrete derived types.
Snapshots regenerated.
Both stages used implicit succeeded(), which is transitive across the
full ancestor graph. A MyGet failure (or a NuGet failure on a re-run
where the version is already published) would therefore cascade-skip
both stages even though their own work is independent of those feeds.
Switch them to inspect dependencies.Deploy_NuGet.result directly so
they remain eligible when NuGet ran and either succeeded or failed,
while still being skipped when Deploy_NuGet itself was Skipped (e.g.
non-release runs). Upload_API_Docs additionally requires Build_Docs
to have produced artifacts.
Add a manual approval gate (ManualValidation@0 server job) to each
stage so a NuGet failure caused by something genuinely unrecoverable
(e.g. expired API key) doesn't auto-promote npm or docs publishes -
the operator must explicitly approve each downstream stage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add manual deploy to NuGet for when MyGet publish fails.
* Simplified instructions for manual approval.
* Gate NuGet release on MyGet's direct result, not transitive succeeded/failed.
succeeded() and failed() are transitive across the full ancestor graph,
so a failure in Unit/Integration/E2E (which skips Deploy_MyGet) still made
or(succeeded(), failed()) evaluate to true and opened the approval gate
on a broken build. Inspect dependencies.Deploy_MyGet.result instead so
Deploy_NuGet only becomes eligible when MyGet itself actually ran.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ContentTypeSchemaTransformer now filters DocumentTypes through
DeliveryApiSettings.IsAllowedContentType so document types blocked
by AllowedContentTypeAliases / DisallowedContentTypeAliases no longer
leak into the polymorphic union or discriminator mapping.
* Remove obsolete UrlSegment extension methods and update callers. Clarify obsoletion of UrlSegment property for Umbraco 19.
* Use 20 for the new obsoletions.
* Align all existing obsolete and non-obsolete calls to retrieve a URL segment to use IDocumentUrlService.
* Fix failing tests.
* Revert incorrectly updated obsoletion removal version.
* extend icons with information from theseaurus
* implement new icon search logic
* clean-up data
* sorting with a backup of the name
* refactor into a controller
* improve multi word group search
* embed lucide data
* rename tech into technology
* remove paper from dollar
* implement fuzzy search for property editor UIs
* minor style update
* improve property editor UI search
* improve search
* improve search data for Property Editor UIs
* remove alias search from property editor ui search
* add usage keywords
* Property editor Suggestions based on Property Label
* related should not show up in search
* rename to suggestionQuery
* update threshold
* separate name words
* also consider full icon name match
* better comment
* other approach for full name matches
* full icon name search if query contains a -
* fix test
* cache all tokens as well
* catch rejection
* resolve feedback
* handle rejected promise
* cancel debounce on disconnect
Co-authored-by: Copilot <copilot@github.com>
* declare voids
* corrections
Co-authored-by: Copilot <copilot@github.com>
* back out if no tokens
---------
Co-authored-by: Copilot <copilot@github.com>
* Implements `auditLog` kind for Elements
* Implements `contentRollback` kind for Elements
* Adds JSDoc comments to element rollback repository and data source
* Exports `UMB_ELEMENT_AUDIT_LOG_REPOSITORY_ALIAS` from `@umbraco-cms/backoffice/element`
Surfaces the constant through the element audit-log barrel so it's available on the public package entry, matching the documents audit-log pattern.
* Added `rollbackNotificationMessage` for Element Rollback
---------
Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
* Adding a more detailed error message when deleting a logged in user
* Fixing overlooked integration test
* Fixing enum binary mistake. Appending enum to the end rather than in the middle.
* Introducing better naming for the enum
* Add element-level extension methods for variance, culture, fallback support
Published Element Extensions now support the same culture, type-checking,
equality, and creator/writer methods that were previously only available
on Published Content Extensions. Content extensions delegate to the
element versions, preserving backwards compatibility.
New element extensions (Core):
- HasCulture, IsInvariantOrHasCulture, CultureDate
- IsDocumentType (both overloads)
- IsEqual, IsNotEqual
- GetCreatorName, GetWriterName
- HasValue with IPublishedValueFallback and Fallback support
New friendly element wrappers (Web.Common):
- Name, CultureDate, CreatorName, WriterName
New non-friendly element extensions (Web.Common):
- CreatorName, WriterName (with IUserService parameter)
* Add unit tests for PublishedElement extension methods
Tests for core extensions (HasCulture, IsInvariantOrHasCulture,
CultureDate, IsDocumentType, IsEqual/IsNotEqual, GetCreatorName,
GetWriterName, HasValue with fallback) and friendly wrappers (Name,
CultureDate, CreatorName, WriterName). All mocks use MockBehavior.Strict.
* Fix empty XML doc param tag for variationContextAccessor in CultureDate
* Delegate content CreatorName/WriterName to element friendly extensions, remove redundant UserService field
* Address PR review: restore StaticServiceProvider in TearDown, use case-insensitive culture dictionary in tests
* Add remarks note about Fallback.ToAncestors not being supported at element level
* Clarify the casting for readability
---------
Co-authored-by: kjac <kja@umbraco.dk>
* Added api helper for reset auth state
* Added more constant variables for login and forgot password message
* Added ui helper for login page
* Added api helper for smtp
* Added tests for backoffice login
* Added tests for backoffice logout
* Added tests for forgot password
* Added api helper for user
* Make tests run in the pipeline
* Updated appsetting to enable reset password
* Added more waits
* Added waits
* Updated locator
* Fix flaky tests
* Updated confirmation message
* Fixed comments
* Removed unused code
* Reverted npm command
* Update Umbraco extension template for OpenAPI route changes
Following the migration from Swashbuckle to Microsoft.AspNetCore.OpenApi
in #21058, the extension template still pointed at the old Swagger URL
pattern and used outdated terminology in code comments.
- generate-client npm script now points at /umbraco/openapi/{name}.json
instead of /umbraco/swagger/{name}/swagger.json
- generate-openapi.js renames swaggerUrl to openApiUrl and updates the
example URL in the missing-argument error message
- UmbracoExtensionApiComposer.cs comments updated from "Swagger" to
"OpenAPI"
* Scope custom OpenAPI document to extension's own endpoints
Without an explicit ShouldInclude predicate, Microsoft.AspNetCore.OpenApi
only includes endpoints whose ApiExplorer GroupName equals the document
name. The template's controller declared a different group name, so the
custom document was created but stayed empty (paths: []), which in turn
made npm run generate-client produce an empty TypeScript SDK.
Filter by the [MapToApi] attribute already present on the extension's
controller base, mirroring the pattern used by the Management and
Delivery API options.
* Add Microsoft.AspNetCore.OpenApi reference to Central package management
The PerProject mode of the umbraco-extension template took a direct
dependency on Microsoft.AspNetCore.OpenApi (with a long comment
explaining why) but the Central mode did not, so default Central
scaffolds failed to build with the source-generator interceptors
error. Mirror the dependency in the Central csproj block and
Directory.Packages.props.
* Remove obsolete logger configuration extensions.
* Removed obsolete database table DTO and constants.
* Removed obsolete LogFiles constant.
* Moved SuperUserId constants obsoletion to 19.
* Remove further reference to removed table.
* Comment out reference to removed table in migration that is also for removal for 18.
* Remove further obsolete methods from LoggerConfigExtensions
* Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Add ModelState.IsValid validation in controller action
* Update method documentation and return simple BadRequest response (aligns with other usages, e.g. BackOfficeController.Verify2FACode).
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* remove inheritance of readonly state
* keep rendering edit in read-only mode
* INVARIANT variant id as static
* parse readonly state, without variant ids as origin is the property read-only state
* stop inheriting read only
* no need for async
* setup read only state based on user permissions
* simplify document-block-property-level-permissions
* make isPermittedForObservableVariant return undefined in bad case
* revert
* improve life cycle for extension initializer
* fix and clean-up
* clean up
* unit test for the actual problem
* clean up
* clean up
* revert logic
* transform access context into local controller
* re-introduce submit create button
* simplify match
* update js docs
* strict compare on config object level, to cover multiple conditions of the same alias.
* Revert "transform access context into local controller"
This reverts commit 1a83d9586b.
* rename file in manifest
* RTE: set manager readOnly
* set fallback on readOnly
* inherit readOnly state when block workspace is invariant
* read-only tag for Block Workspace
* make guard fallback reactive
* observe readOnly languages
* no if sentence
* observe fallback for property + name guards
* prevent cancelled context get to cause problems
* revert removal of || this._isReadOnly check for component rendering
* add comment for clarification
* remove style import
* mark as readonly and make js-const
* remove `as const`
* unit test for reactive fallback feature
* more guard unit tests
* more variantId tests
* move block language access controller to block package
* Update base-extension-initializer.controller.ts
* fix test
* improve switch condition
* offset condition
* Block Workspace: Add data-mark for acceptance test locator
* apply entity-type to the workspace data-mark
* layout-headline
* Updated locator to use new data-mark
* Updated tests to make them less fragile
* null ctrl alias for constructor initiated observations
* import directly
* do not react to not existing user-data or missing context
* add comment
* refactor package registration logic
* package name for code editor
* leave unregistere out
* await load all bundles
Co-authored-by: Copilot <copilot@github.com>
* move initializer to app element
* Batch register extensions with validation
* remove await on load for extension initializers
* Debounce extension updates and set loaded flag
* remove unused imports
* refactor backoffice -> app
* clean up imports
* rename comment
Co-authored-by: Copilot <copilot@github.com>
* base extension initializer is loaded update
* app loader
Co-authored-by: Copilot <copilot@github.com>
* embed umbraco-packages
* remove lazy loads from dataSourceDataMapper
* revert
* enable routes to be undefined
Co-authored-by: Copilot <copilot@github.com>
* comment
Co-authored-by: Copilot <copilot@github.com>
* make sure load only calls once
Co-authored-by: Copilot <copilot@github.com>
* comments and todos
* destroy consumer if existing
* block language access tests
* load user at the end of loading all package modules
* assign symbol for is-trashed observer
* revert language readonly rules
Co-authored-by: Copilot <copilot@github.com>
* is-trashed context + observation
Co-authored-by: Copilot <copilot@github.com>
* read-only as view prop for block list
Co-authored-by: Copilot <copilot@github.com>
* readonly as view prop
* readonly prop for grid,rte,single
Co-authored-by: Copilot <copilot@github.com>
---------
Co-authored-by: Mads Rasmussen <madsr@hey.com>
Co-authored-by: Andreas Zerbst <andr317c@live.dk>
Co-authored-by: Copilot <copilot@github.com>
* Avoid render structure view when element type is active
* Avoid render history clean up when is an element type
* Replace hidden sections with inline "not applicable" message for Element Types
---------
Co-authored-by: Mads Rasmussen <madsr@hey.com>
Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
Mark HttpClient IgnoreCertificateErrors as obsolete due to security risk and add TODO to remove in a future release
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
* feat(block): add blockAction extension type for extensible block entry actions
Introduce a new `blockAction` extension type that allows both internal and
3rd-party extensions to register actions on block items. This replaces the
hardcoded Delete button on Block List entries with an extension-registered
action, while keeping Edit Content, Edit Settings, and Copy to Clipboard
as slotted content for incremental migration.
The new `<umb-block-action-list>` element owns the `<uui-action-bar>` and
renders a `<slot>` for hardcoded actions followed by extension-registered
`blockAction` extensions, enabling one-by-one migration of actions.
* feat(block): apply blockAction extension to grid, rte, and single block editors
Extend the blockAction pattern to all remaining block entry elements.
Each editor now uses <umb-block-action-list> with slotted hardcoded
actions and the Delete action registered via the extension registry.
* fix(block): render blockAction extensions directly in uui-action-bar
Replace umb-extension-with-api-slot with UmbExtensionsElementAndApiInitializer
to render blockAction elements as direct children of uui-action-bar. This fixes
the border-radius issue where the wrapper element broke :first-child/:last-child
structural selectors used by uui-action-bar for button styling.
* refactor(block): replace showOnReadOnly meta with BlockEntryIsReadOnly condition
Add a new Umb.Condition.BlockEntryIsReadOnly condition that checks the
read-only state from UMB_BLOCK_ENTRY_CONTEXT. This replaces the inline
read-only guard and showOnReadOnly meta flag on the default kind element.
Delete action uses the condition with match: false (hidden when read-only).
Copy to Clipboard has no condition (always visible). 3rd-party actions
opt in to read-only gating by adding the condition to their manifest.
* feat(block): migrate clipboard copy to blockAction extension
Move the Copy to Clipboard action from hardcoded buttons to a registered
blockAction extension across all four block editors. The copy logic is
moved from each entry element into its respective entry context, with a
base copyToClipboard() method on UmbBlockEntryContext.
* docs(block): add plan for migrating Edit Content and Edit Settings to blockAction
* feat(block): migrate Edit Settings to blockAction extension
Replace the hardcoded Edit Settings button with a blockAction extension
using the default kind. The API class provides getHref() for workspace
navigation and getValidationDataPath() for the invalid badge.
Adds getValidationDataPath() to the UmbBlockAction interface and default
kind element, enabling any blockAction to display a validation badge.
Introduces Umb.Condition.BlockEntryHasSettings condition to control
visibility based on whether the block has a settings element type.
* feat(block): migrate Edit Content to blockAction extensions
Split the hardcoded Edit Content button into two blockAction extensions
controlled by manifest conditions:
- Umb.BlockAction.EditContent — navigates to workspace content view,
shows validation badge via getValidationDataPath()
- Umb.BlockAction.ExposeContent — calls context.expose() when block
is not yet exposed and content edit is hidden
Adds match support to BlockEntryShowContentEdit condition and creates
a new BlockEntryIsExposed condition at the entry level.
Removes the <slot> from umb-block-action-list — all block entry actions
are now fully driven by the extension registry.
* Removes plan/spec files
* chore(block): address review findings for blockAction feature
- Add TODO comment for stale getHref/getValidationDataPath (I-1)
- Remove orphaned @state() properties from all four entry elements (I-2)
- Add UMB_BLOCK_ENTRY_SHOW_CONTENT_EDIT_CONDITION_ALIAS constant and
replace string literals in edit-content/expose-content manifests (I-3)
- Change Expose Content weight from 400 to 399 (S-1)
- Add JSDoc to exported types and classes (S-2)
- Fix condition import alias — rename workspace-level to
UmbBlockWorkspaceIsExposedCondition (S-3)
* fix(block): revert CSS custom property rename to preserve backwards compatibility
Restore the original per-editor CSS custom property names:
--umb-block-list-entry-actions-opacity, --umb-block-grid-entry-actions-opacity,
--umb-block-single-entry-actions-opacity. The action bar opacity styles are
now back in each entry element (using #actions selector), so the unified
property name is no longer needed.
* fix(block): address PR review feedback from Copilot and Claude bots
- Fix Expose button label regression — replace dynamic
'#blockEditor_createThisFor' (function key) with static '#actions_create'
so the button no longer renders "Create undefined"
- Guard empty-string href in EditContent and EditSettings actions —
'workspaceEdit{Content,Settings}Path' emits '' before ready; return
undefined instead of '' so the button doesn't get href="" (which would
navigate to the base URL on click)
- Clear _href in default kind api setter — prevents stale href when the
api is replaced or set to undefined
- Fix barrel imports in 3 block entry conditions — import
UMB_BLOCK_ENTRY_CONTEXT directly from context-token.js rather than via
the ../index.js barrel, reducing circular dependency risk
- Make block-action-list reactive to contentTypeAlias changes — the
extensions initializer is now re-created when unique or
contentTypeAlias changes, so forContentTypeAlias filters apply
correctly when contentTypeAlias resolves asynchronously
- Throw in base copyToClipboard() — the default no-op on
UmbBlockEntryContext now throws rather than logging a warning, so any
future subclass that fails to override fails visibly
Tests for the new conditions were attempted but deferred to follow-up;
context observable mocking semantics need more investigation.
* fix(block): restore uui-action-bar styling on block-action buttons
Remove the `compact` attribute from the inner `<uui-button>` and bridge
the CSS custom properties set by `uui-action-bar::slotted(*:first-child)`
etc. through `<umb-block-action>`'s shadow DOM via intermediate
`--umb-button-*` variables. Without this bridge, `uui-button`'s own
`:host` declarations shadow the inherited values and the first/last
button border-radius + padding don't apply.
* fix(block): address second-pass PR review feedback
- Throw when RTE editor manifest is missing so clipboard entries are
never written with an empty propertyEditorUiAlias (would silently
fail to match on paste)
- Replace bare `return` with `return nothing` in default kind element
render() for type-level clarity
- Add class-level JSDoc to exported block action classes
(UmbEditContentBlockAction, UmbEditSettingsBlockAction,
UmbDeleteBlockAction, UmbCopyToClipboardBlockAction,
UmbExposeContentBlockAction) and UmbBlockActionDefaultElement
* refactor(block): reduce copyToClipboard complexity per CodeScene feedback
Extract `#buildPropertyValue()` helper in List, RTE, and Single entry
contexts to move the four content/layout/settings/expose ternaries out
of copyToClipboard, lowering its cyclomatic complexity.
Split the compound `||` context guards into sequential early-return
checks so each missing context throws with a specific error message,
and the "Complex Conditional" smell is removed.
* refactor(block): further reduce RTE copyToClipboard complexity
Consolidate three sequential `await getContext(...)` calls into a single
`Promise.all`, dropping the cyclomatic complexity below CodeScene's
threshold of 9.
* refactor(block): extract RTE clipboard write into helper method
Split the post-guard write phase into `#writeClipboardEntry` to bring
both methods well under CodeScene's cyclomatic complexity threshold.
* clean up action
Co-authored-by: Copilot <copilot@github.com>
* show edit content / settings despite read-only state
---------
Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
* Rename "Master Template" to "Layout Template" throughout the codebase
Since Umbraco switched from WebForms to MVC, the "Master" template
terminology has been incorrect — in Razor/MVC the parent template is
called a "Layout", not a "Master page". This renames the concept across
C# models, services, repositories, the Management API, and the
backoffice frontend while preserving backward compatibility via
[Obsolete] members scheduled for removal in Umbraco 20.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Remove dead template layout XML element code and rename test methods
The serializer code that wrote <Master>/<MasterAlias> elements was never
executed because Lazy<int>.IsValueCreated was always false after loading
from the database. The corresponding import code that read these elements
was equally dead since no package.xml ever contained them. Template
parent-child hierarchy is resolved from Razor Layout directives instead.
Also renames 4 test methods from "Master" to "Layout" to match the
updated terminology.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Packaging: Suppress noisy log when imported Template has no Layout
A null Layout is legitimate for root layout files (e.g. `Layout = null;`)
and shouldn't be reported as "invalid". Only log when a non-null Layout
was referenced but couldn't be resolved in the import.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Update acceptance tests and further references in comments.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Sebastiaan Janssen <sebastiaan@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Use InvariantCulture when parsing node paths.
* Add suggested validation of setup to integration test.
* Add more explicit tests for negative sign handling
---------
Co-authored-by: kjac <kja@umbraco.dk>
fix(core): clear element entity cache on content type changes
The ContentTypeCacheRefresher clears IContent isolated cache when a
content type changes, but did not clear IElement cache. This caused
stale element entities to be returned after modifying property type
variation settings (e.g. enabling vary-by-culture), leading to 500
errors when saving elements.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Prevent creation of redirects when the old route is unroutable.
* Addressed code review feedback.
* Extend fix to handle case where a second, child page is "redirected" after preview was left open.
(cherry picked from commit 728789aaf6)
* Ensure published querying parity between V13 and V17
* Add unit tests for published ancestor path querying
* Fix Claude review comments
* Make Unfiltered() public on the interface
* Explicitly evaluate "unfiltered" items
* A little clean-up
* Add integration tests
* Addressed code review feedback.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Prevent creation of redirects when the old route is unroutable.
* Addressed code review feedback.
* Extend fix to handle case where a second, child page is "redirected" after preview was left open.
* Uninstall `Swashbuckle.AspNetCore` and install `Microsoft.AspNetCore.OpenApi`
Also installed `Swashbuckle.AspNetCore.SwaggerUI` for now to use as UI only.
* Registered UI and removed or commented out Swashbuckle specific code
* Started configuring the different Open API documents
* Started moving configuration
* Simplifying configuration
* Added missing configuration for the Delivery API
* Added missing configurations for Management API
Still missing polymorphism settings for both APIs
* Adjust Umbraco Extension template with OpenApi changes
* Handle sub types in open api document generation
* Renaming mime types transformer to align with others
* Added discriminator configuration
* Reference Umbraco.Cms.DevelopmentMode.Backoffice from integration tests project to avoid models mode exception being logged in tests
* Now configuring and using the HTTP json options instead of having custom transformers for handling enums and polymorphism
* Fixes to examples
* Update OpenAPI packages
* Mark most transformers as internal
* Simplify adding backoffice security requirements to your API
* Fix missing required properties
* Re-order transformers to fix missing notification headers
* Fix most build errors after regenerating client
* Fix mime types transformer being applied to Management API
* Additional fixes
* Additional fixes to file response types
* Configure Swagger UI documents
* Clear server list
* Sort APIs in UI
* Re-introduce schema handlers and fix issue with nullable enum schema name
* Simplify examples
* Small optimization
* Simplify nullability check in RequireNonNullablePropertiesSchemaTransformer
* Remove unused property
* Small fixes suggested by Claude
* Undo unintended space changes
* Add unit tests for OpenAPI transformers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add unit tests for additional OpenAPI transformers
- RequireNonNullablePropertiesSchemaTransformer (7 tests)
- BackOfficeSecurityRequirementsTransformer (10 tests)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Rename SwaggerGen classes to OpenApi for consistency
- Rename ConfigureUmbracoDeliveryApiSwaggerGenOptions to ConfigureUmbracoDeliveryApiOpenApiOptions
- Rename ConfigureUmbracoMemberAuthenticationDeliveryApiSwaggerGenOptions to ConfigureUmbracoMemberAuthenticationDeliveryApiOpenApiOptions
- Rename ConfigureUmbracoManagementApiSwaggerGenOptions to ConfigureUmbracoManagementApiOpenApiOptions
- Rename SwaggerRouteTemplatePipelineFilter to OpenApiRouteTemplatePipelineFilter
- Update DI registrations to use new class names
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update OpenAPI contract test for Microsoft.AspNetCore.OpenApi
Update expected Delivery API OpenAPI contract to reflect changes from
the migration to Microsoft.AspNetCore.OpenApi:
- OpenAPI version 3.0.4 → 3.1.1
- Nullable types now use type array format (OpenAPI 3.1 style)
- Polymorphic types use anyOf with discriminator
- Security moved from header parameter to securitySchemes
- Removed unnecessary oneOf wrappers around single $ref
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Disable Models Builder in integration tests by default
* Rename Swagger references to OpenApi for consistency
- Rename SwaggerIsEnabled to OpenApiIsEnabled
- Rename SwaggerRouteTemplate to OpenApiRouteTemplate
- Rename SwaggerUiRoutePrefix to OpenApiUiRoutePrefix
- Rename SwaggerUiConfiguration to ConfigureOpenApiUI
- Rename swaggerPipelineFilter variable to openApiPipelineFilter
- Update code comments from "Swagger JSON" to "OpenAPI specification"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Re-generate Management API open api doc and UI client after merge
* Add reference in comment to additional PR to fix file return types schema
* Fix Open API validation errors
* OpenAPI: Replace ISchemaIdHandler/ISchemaIdSelector with static UmbracoSchemaIdGenerator
Remove the DI-based schema ID handler/selector pattern and replace with a
static UmbracoSchemaIdGenerator utility class. This allows both Umbraco code
and external consumers to call the schema ID generation logic directly, which
is useful since the Microsoft OpenAPI package's schema selectors only apply
to Umbraco's own OpenAPI documents.
- Remove ISchemaIdHandler, ISchemaIdSelector interfaces and implementations
- Add static UmbracoSchemaIdGenerator.Generate() method
- Update ConfigureUmbracoOpenApiOptionsBase to use UmbracoSchemaIdGenerator directly
- Remove constructor dependencies from API options classes
- Add unit tests for UmbracoSchemaIdGenerator and CreateSchemaReferenceId
* Rename CustomOperationIdsTransformer to UmbracoOperationIdTransformer and make public
- Rename class to better reflect its purpose as Umbraco's operation ID transformer
- Change visibility from internal to public so it can be used by external consumers
- Update XML documentation to clarify usage for custom OpenAPI configurations
* OpenAPI: Update Delivery API contract test for new document format
Update expected OpenAPI output to include explicit empty values in
examples and consistent array formatting in security requirements.
* OpenAPI: Remove obsolete DocumentInclusionSelector abstraction
The document inclusion logic is now handled directly by
ConfigureUmbracoOpenApiOptionsBase.ShouldInclude(), making
the separate IDocumentInclusionSelector abstraction unnecessary.
* OpenAPI: Reorganize Management API OpenApi folder structure
- Move transformers to OpenApi/Transformers subfolder
- Move OpenApiOptionsExtensions from Extensions to OpenApi folder
- Update namespaces accordingly:
- Umbraco.Cms.Api.Management.OpenApi.Transformers (transformers)
- Umbraco.Cms.Api.Management.OpenApi (extensions)
* OpenAPI: Add ExcludeFromDefaultOpenApiDocument attribute
- Add [ExcludeFromDefaultOpenApiDocument] attribute for excluding controllers from the default OpenAPI document
- Make ShouldInclude method protected virtual in ConfigureUmbracoOpenApiOptionsBase for extensibility
- Override ShouldInclude in ConfigureDefaultApiOptions to check for the exclusion attribute
* OpenAPI: Add UmbracoOpenApiOptions for configuring OpenAPI routes
Add UmbracoOpenApiOptions configuration class to allow customizing:
- Enabled: Enable/disable OpenAPI and Swagger UI (default: non-production)
- RouteTemplate: Route template for OpenAPI JSON documents
- UiRoutePrefix: Route prefix for Swagger UI
Umbraco sets defaults via Configure, users can override via PostConfigure.
Simplify OpenApiRouteTemplatePipelineFilter to use options directly.
* Pipeline filters: Add OnPreMapEndpoints and rename OnEndpoints to OnPreEndpoints
- Add OnPreMapEndpoints method to IUmbracoPipelineFilter for registering
endpoints inside UseEndpoints without calling UseEndpoints twice
- Rename OnEndpoints to OnPreEndpoints (with backward-compatible default)
- Add PreMapEndpoints and PreEndpoints properties to UmbracoPipelineFilter
- Mark OnEndpoints and Endpoints as obsolete (removal in Umbraco 19)
- Update UmbracoApplicationBuilder to call OnPreMapEndpoints inside UseEndpoints
- Remove redundant UseEndpoints() call from BackOfficeManagementApiFilter
- Update LoadTestController to use PreMapEndpoints instead of Endpoints
Co-Authored-By: Claude <noreply@anthropic.com>
* OpenAPI: Move MapOpenApi to PreMapEndpoints hook
Move OpenAPI endpoint mapping from PostPipeline to PreMapEndpoints
to avoid calling UseEndpoints twice in the pipeline.
* OpenAPI: Rename URL paths from swagger to openapi
- Change OpenAPI UI and document URLs from /umbraco/swagger to /umbraco/openapi
- Rename OAuth client constant from Swagger to OpenApiUi (value kept as
umbraco-swagger for backwards compatibility with existing DB registrations)
- Update display name to "Umbraco OpenAPI access"
- Add DefaultUiEnabled option to allow disabling the default UI while
keeping OpenAPI documents available (enables use of alternative UIs)
- Update MiniProfiler ignored path
Co-Authored-By: Claude <noreply@anthropic.com>
* OpenAPI: Update Microsoft.AspNetCore.OpenApi to 10.0.2
* OpenAPI: Add AddOpenApiDocumentToUi extension method
Adds a public extension method to simplify adding OpenAPI documents to the
UI document selector. This respects the configured UmbracoOpenApiOptions
route template, so users don't need to hardcode paths.
The documentTitle parameter is optional and defaults to the documentName.
Also updates the UmbracoExtension template to use the new method and
fixes the documentation URL reference.
* OpenAPI: Make OpenApiRouteTemplatePipelineFilter internal
The class has no extension points (all methods are private static) and
customization is now done via UmbracoOpenApiOptions instead.
* OpenAPI: Rename DeliveryApiSecurityFilter to DeliveryApiSecurityTransformer
Aligns naming with other OpenAPI transformers for consistency.
* OpenAPI: Simplify Delivery API member authentication configuration
Replace ConfigureUmbracoMemberAuthenticationDeliveryApiOpenApiOptions with
a simpler AddDeliveryApiOpenApiMemberAuthentication() extension method on
IServiceCollection. This hides implementation details and provides a cleaner
API for users to enable member authentication in the Delivery API OpenAPI document.
* OpenAPI: Add reference to proposal for custom JSON options support
* Move Delivery API transformers to OpenApi/Transformers folder
Aligns the folder structure with the Management API project.
* Update OpenAPI contract tests to use new URL format
Changed from /swagger/{name}/swagger.json to /openapi/{name}.json
* Apply suggestions from code review
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Fix IAuthorizationService injection detection in BackOfficeSecurityRequirementsTransformer
- Fix bug where parameter.GetType() was used instead of parameter.ParameterType,
causing the IAuthorizationService injection check to always return false
- Replace magic number with BaseAuthorizeAttributeCount constant
- Improve comments explaining the 403 response logic
- Add test for IAuthorizationService injection detection
* Remove unnecessary InterceptorsNamespaces from API projects
* Remove default implementations from IUmbracoPipelineFilter methods
* Update documentation for Microsoft.AspNetCore.OpenApi migration
- Update CLAUDE.md files to reflect the migration from Swashbuckle to Microsoft.AspNetCore.OpenApi for document generation
- Update URL paths from /umbraco/swagger/ to /umbraco/openapi/
- Rename swaggerPath variables to openApiPath in test files
- Update references to removed types (SchemaIdHandler, OperationIdHandler, etc.) with their new equivalents (UmbracoSchemaIdGenerator, UmbracoOperationIdTransformer)
- Remove outdated technical debt reference to deleted SwaggerDocumentationFilterBase
* Update Swashbuckle.AspNetCore.SwaggerUI to 10.1.2
Fixes browser caching behavior and document URL serialization issues.
* Refactor OpenAPI contract tests with validation
- Add OpenAPI spec validation for both Delivery and Management APIs
- Delivery API: Store expected contract in external JSON file for regression testing
- Management API: Compare generated contract against expected contract endpoint
- Organize Delivery API tests under OpenApi/ subdirectory
- Auto-generate Delivery API contract file if it doesn't exist
* Update ElementReferenceResponseModel type reference after OpenAPI regeneration
* Add discriminator values to Delivery API polymorphic JSON serialization
ConfigureJsonPolymorphismOptions now passes derivedType.Name as the
discriminator value for each JsonDerivedType, ensuring the $type property
is present in responses and the OpenAPI schema is valid.
* Move Delivery API OpenAPI contract tests to Umbraco.Api.Delivery folder
* Update Microsoft.AspNetCore.OpenApi to 10.0.3 and Swashbuckle.AspNetCore.SwaggerUI to 10.1.4
* Use JsonDerivedType attributes for Delivery API polymorphic serialization
Move discriminator configuration from ContentJsonTypeResolverBase to
JsonDerivedType attributes on the interfaces. This is the standard STJ
approach and keeps the resolver available for custom overrides only.
* Add OpenAPI test for custom derived type extensibility
Extract shared test infrastructure into OpenApiTestBase and add
OpenApiCustomDerivedTypeTest to verify the OpenAPI spec remains valid
when a consumer registers a custom derived type via
ContentJsonTypeResolverBase.GetDerivedTypes.
* Fix OpenAPI contract test failing on CI due to ContinuousIntegrationBuild path normalization
[CallerFilePath] embeds a compile-time source path that gets normalized to /_/... on Azure DevOps
agents when ContinuousIntegrationBuild=true. At runtime the expected contract file is not found at
that path, causing the test to attempt Directory.CreateDirectory("/_/...") which fails with
permission denied.
Fix by reading contract files from the output directory (CopyToOutputDirectory) instead of the
compile-time source path. The [CallerFilePath] approach is kept only for writing new contracts
during local development, wrapped in a try/catch so it fails gracefully on CI.
* Bump Swashbuckle.AspNetCore.SwaggerUI to 10.1.7
* Remove duplicate InternalsVisibleTo for Umbraco.Tests.UnitTests
* Extract ReplaceOpenApiSchemaService into shared Api.Common helper
Deduplicates the internal OpenApiSchemaService replacement logic
between Management API and Delivery API into a single internal
extension method in Umbraco.Cms.Api.Common. Uses assembly and type
name checks derived from a public type (OpenApiOptions) instead of
hardcoded strings for safer matching.
* Tighten visibility and improve DI extension structure
- Mark FixFileReturnTypesTransformer as internal (temporary workaround)
- Mark AddUmbracoApiOpenApiUI and AddUmbracoApi as internal
- Rename AddUmbracoApi to AddUmbracoOpenApiDocument on IUmbracoBuilder
- Move AddOpenApiDocumentToUi to OpenApiServiceCollectionExtensions
- Encapsulate ReplaceOpenApiSchemaService inside AddUmbracoOpenApiDocument
as an optional jsonOptionsName parameter
* Regenerate OpenApi.json to fix duplicate document patch endpoint
* Move MimeTypesTransformer to shared base and respect [Consumes]
Moves the MIME type filtering from a Delivery API-only document
transformer to a shared operation transformer in Api.Common. When
[Consumes] is present, replaces content types with exactly what it
declares (fixing application/json-patch+json on the patch endpoint).
Otherwise strips non-application/json types. Regenerates OpenApi.json
and client SDK.
* Move Umbraco-specific transformers from shared base to API configs
RequireNonNullablePropertiesSchemaTransformer, FixFileReturnTypes
Transformer, and MimeTypesTransformer are now registered only in
the Management and Delivery API configs. The default API document
(used for consumer endpoints) no longer applies these opinionated
transformers.
* Clarify XML doc for UmbracoOpenApiOptions.Enabled
* Use alphabetically-first tag across all operations for stable path sorting
* Update MimeTypesTransformer tests for operation transformer interface
* Reference dotnet/aspnetcore#66340 in ReplaceOpenApiSchemaService docs
* Add unit tests to verify OpenApiSchemaServiceExtensions usage of internal types.
* Bumped Microsoft.AspNetCore.OpenApi from 10.0.4 to 10.0.6 to match Directory.Packages.props and removed unnecessary Swashbuckle reference.
* Fix indentation.
* Defensively handle a non-integer status code response key in ResponseHeaderTransformer.
* Use TryGetValue in RequireNonNullablePropertiesSchemaTransformer to avoid potential KeyNotFoundException.
* Additional tests and clarifying comments.
* Revert accidental local dev changes to Program.cs, Web.UI.csproj and StaticAssets.csproj.
* Tighten visibility of OpenAPI configuration and transformer classes to internal
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Updated element creation step due to UI changes
* Updated element creation due to UI changes - cont
* Removed unused locator
* Updated locator for elementTreeItem
* Updated tests for library to match the UI changes
* Updated locator for elementVariantDropdown
* Updated tests for element permission and start nodes
* Removed @smoke tags
* Make tests run in the pipeline
* Added comment for failing tests
* Updated tests for element start nodes as the front-end does not support adding a element as start nodes
* Fix flaky tests
* Fixed comment
* Removed obsolete methods and default implementations on IEmailSender.
* Removed the obsolete and unused MemberConfigurationResponseModel.
* Remove the obsolete MediaPermissions and ensure test coverage is maintained.
* Extends `UmbContentRollbackModalValue` with `UmbEntityModel`
so that the Rollback modal can return the entity-type,
to display the correct notification message.
* Housekeeping
* Added localized fallback key
* Fixed typecasting issue for deprecated Document rollback
* Reverted logic, introduced `rollbackNotificationMessage` meta prop
* Added constant variables for audit trail
* Added ui helper for audit trail
* Added tests for audit trails in content
* Added test for audit trail when trash content
* Added tests for audit trail when sort. move and rollback content
* Added tests for audit trail when bulk actions
* Updated tests for creating content
* Fixed comment
* bug(#22607) Add Directory.Packages.props and update restore command
Updated Dockerfile to include Directory.Packages.props and modified restore command to resolve docker build errors during dotnet restore step. Resolves issue #22607
* fix(template): conditionally copy Directory.Packages.props in Dockerfile
Only copy Directory.Packages.props when CPM is enabled, as per-project
package management users won't have this file in their build context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: mole <nikolajlauridsen@protonmail.ch>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit df3cd50e7f)
* Generate random guid for cert pass
* Changes from review
* Move cert generation and add script to trust cert on host machine
* Generate simple hmac key
(cherry picked from commit fcf5af3d16)
* bug(#22607) Add Directory.Packages.props and update restore command
Updated Dockerfile to include Directory.Packages.props and modified restore command to resolve docker build errors during dotnet restore step. Resolves issue #22607
* fix(template): conditionally copy Directory.Packages.props in Dockerfile
Only copy Directory.Packages.props when CPM is enabled, as per-project
package management users won't have this file in their build context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: mole <nikolajlauridsen@protonmail.ch>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* add redirect tracking workspace
* change weight to match v13 order
* add missing alignment and text colour
* Align closer with referency by element
* Ad repository pattern from review
* remove obsolete
* Update src/Umbraco.Web.UI.Client/src/packages/documents/documents/redirect-management/info-app/document-redirect-management-workspace-info-app.element.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Adds JSDocs
* Removed unused `created` and `documentUnique` from `UmbDocumentRedirectUrlModel`
* Align `setStatus` and `delete` return shape with other data source methods
* Align workspace context observer with sibling info-app pattern
* Polish dashboard and info-app: localize hardcoded strings, tidy templates and imports
* Apply review simplifications
- Drop duplicate `unique` guards from data source (kept at repository boundary)
- Drop unnecessary `?? []` fallbacks (`items` is non-nullable in the API type)
- Localize hardcoded zero-results strings in dashboard
- Simplify redundant length check in info-app `#getTargetUrl`
- Drop unused `userIsAdmin` from `UmbDocumentRedirectStatusModel`
---------
Co-authored-by: leekelleher <leekelleher@gmail.com>
* Mark RTE as supports read only
* RTE: Address read-only review feedback
- Remove `pointer-events: none` from `:host([readonly])` so users can select and copy text in read-only mode
- Make the editor's editable state reactive to the `readonly` property via `setEditable`
- Skip rendering the statusbar in read-only mode (mirrors the toolbar) to avoid the missing border-radius regression
- Remove the now-unused `readonly` property from `umb-tiptap-toolbar` and `umb-tiptap-statusbar`
---------
Co-authored-by: leekelleher <leekelleher@gmail.com>
* init current user workspace
* adding current user workspace and their apis
* add new controllers
* add default implementation
* Update src/Umbraco.Core/Services/UserService.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Cms.Api.Management/ViewModels/User/UpdateCurrentUserRequestModel.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update tests/Umbraco.Tests.Integration/Umbraco.Core/Services/UserServiceCrudTests.Update.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Core/Models/CurrentUserUpdateModel.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* update openApi.json, remove userKey from model, remove redundant authentication check from controllers
* update localize
* allow blob: URLs in img-src CSP for avatar
* save image change later
* Remove references to "current" user from service layer.
Align validation for user profile update with update user service method.
Controller tidy-up of dependencies.
* Add missing controller from last commit.
* resolve conflicts 2
* Renamed/relocated "current-user-workspace" to "profile/edit"
Refactored the "Edit" (profile) button logic,
to handle the check whether the user has access to the Users section.
* Removed the "Section User No Permission" condition
as no longer used.
* UI tweaks + streamlining
* Profile edit: surface save errors and avoid blob URL leak
- Show danger notification when avatar upload/delete or profile update fails
- Refresh current user after avatar upload so the store holds server URLs, not a leaking local blob
- Element save() methods now return boolean; modal keeps itself open when a save fails and no longer double-submits
* Refactored to use `asPromise()`
* Current User: Adapt edit-profile modal into a workspace extension
Replaces Umb.Modal.CurrentUserEditProfile with a workspace registered
against entityType 'current-user'. The UmbSubmittableWorkspaceContextBase
subclass owns the editable user model and pending avatar state; submit()
coordinates uploadAvatar / deleteAvatar / updateProfile and throws on
failure so the workspace stays open, relying on the repository's existing
danger notifications.
The current-user "Edit" action now opens UMB_WORKSPACE_MODAL (sidebar,
small) instead of the bespoke modal. Avatar and settings children become
presentational views wired to the workspace context.
* Current User workspace: Address review findings
- Await initial load promise in submit() to prevent a race where the save
action fires before the first requestCurrentUser() resolves.
- Guard the avatar element's async observer setup against post-disconnect
attachment.
- Document the split between #data (editable persisted state) and
#pendingAvatar (transient UI state) in the workspace context.
- Remove stray JSDoc whitespace in current-user.server.data-source.ts.
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
Co-authored-by: leekelleher <leekelleher@gmail.com>
* fix raw sql with ISqlSyntaxProvider name escaping
* reduce hard coded strings
* Fix Raw Sql in MemberFilterRepository
* fix formating
* restore MemberFilterRepository
* Correct usage of field name constant.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* fix raw sql with ISqlSyntaxProvider name escaping
* reduce hard coded strings
* Fix Raw Sql in MemberFilterRepository
* fix formating
* restore MemberFilterRepository
* Correct usage of field name constant.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Prevent Concurrent_Save_Same_Login_Should_Not_Throw_Duplicate_Key_Exception from failing when exceptions other than what is being guarded against are triggered.
* Addressed code review feedback.
* Generate random guid for cert pass
* Changes from review
* Move cert generation and add script to trust cert on host machine
* Generate simple hmac key
* Add table collection view and manifests
* Use table kind in collection example
* Update entity-name-table-column-layout.element.ts
* Recompute table rows when item hrefs change
* define and render columns from manifest
* wip language implementation
* map to unique field
* rename to label
* test implementation for users table
* clean up
* add example entity actions
* add example description
* Update table-collection-view.element.ts
* Omit base 'meta' and relax table meta type
* Hardcode description column when present
* localize column names
* Update table-collection-view.element.ts
* Type manifest on collection view elements
* Use UmbLitElement instead of LitElement
* fix types
* Update entity-name-table-column-layout.element.ts
* provide entity context for each table row
* fix breaking change and introduce a deprecation warning
* Add status column to example collection view + localize column labels
* implement the UmbTableColumnLayoutElement interface
* add tests for the table collection view
* Make host element optional; add table docs/types
* Update controller-host.mixin.ts
* Update src/Umbraco.Web.UI.Client/src/packages/core/entity-action/global-components/entity-actions-table-column-view/entity-actions-table-column-view.element.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update controller-host.mixin.ts
* Update entity-name-table-column-layout.element.ts
* Update entity-actions-table-column-view.element.ts
* Handle undefined row element in table rendering
Allow onRowRendered to accept an undefined element and clean up row contexts when a row is unmounted. Update the callback signature in table.element.ts and handle the undefined case in table-collection-view.element.ts by destroying the host and removing the stored context for the item to avoid memory leaks when rows are removed.
* Update controller-host.mixin.ts
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
* Align GUID-via-UDI and integer locallink sources in migration to consistent type attribute casing.
* Handle Pascal cased type attributes from local links.
* Preserve segment-specific property values after save and publish.
* Addressed feedback from code review.
* Moved fix to a projection in UmbPropertyValuePresetVariantBuilderController.
---------
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
* Preserve segment-specific property values after save and publish.
* Addressed feedback from code review.
* Moved fix to a projection in UmbPropertyValuePresetVariantBuilderController.
---------
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
* Add XML header comments and unit tests for member operation surface controllers.
* Addressed code review feedback.
* Further code review feedback.
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Add a constant for the "unroutable content" route
* Add one more constant for URL provider exceptions
* Update src/Umbraco.Core/Routing/UrlProviderExtensions.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Core/Constants-Routing.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Conditionally render history & structure settings
* Show "not applicable" message instead of hiding the settings
* Refactored to reuse `#renderElementDoesNotSupport()`
* Modified "Allow in Library"
to display a message instead of hiding the field.
---------
Co-authored-by: leekelleher <leekelleher@gmail.com>
* Definition and validation of minimum range for slide property editor.
* Address code review feedback.
* Treat an incorrectly configured negative minimum range as zero.
---------
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
* Ensure that DocumentUrlService and DocumentUrlAliasService will respect read-only, subscriber databases.
* Fixed breaking change in constructor.
* Clarified comment.
* Use pattern matching in SkipDatabaseWrites() check.
* Ensure that DocumentUrlService and DocumentUrlAliasService will respect read-only, subscriber databases.
* Fixed breaking change in constructor.
* Clarified comment.
* Use pattern matching in SkipDatabaseWrites() check.
* Make ApplicationMainUrl on IHostingEnvironment nullable.
Update usage in HttpsCheck healthcheck and add unit tests to verify refactor.
* Improves XML documentation for the property.
* fix(frontend): use keyed repeat for umb-table columns to fix Firefox rendering (#22411)
Column rendering used .map() without keys, causing Firefox's CSS
table-* layout to break when columns changed after initial render.
Switch to repeat() with column.alias keys so Lit properly inserts/removes
DOM nodes. Also removes a stray </uui-table-cell> closing tag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(frontend): wrap umb-table in Lit `keyed` so Firefox rebuilds the table when columns change
The `repeat()` + alias key change alone did not fix the Firefox issue: Firefox's
`display: table-*` layout engine fails to relayout when cells are inserted into
existing rows, even when Lit's keyed reconciliation does the right thing.
Wrap the `<uui-table>` render in `keyed(columnKey, ...)` so that whenever the
column set changes (keyed on the joined column aliases), Lit discards the entire
subtree and builds a fresh one. Firefox then paints a brand-new table and its
buggy incremental relayout path never runs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* docs(frontend): document UmbTableColumn.alias uniqueness constraint
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(frontend): reattach sorter on column rebuild and harden column key
Address two review comments on the keyed() rebuild:
- UmbSorterController caches its container element on first
initialization, so when keyed() replaces <uui-table> the sorter stays
attached to the detached node. Toggle disable()/enable() in updated()
when the column signature changes and the table is sortable, so the
sorter reattaches to the fresh table.
- Build the column key via JSON.stringify instead of a pipe-joined
string, so aliases containing '|' can't collide and defeat the rebuild.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Content: Clear per-culture published flags when copying a document (closes#22540)
When copying a published culture-variant document, the document-level
published flag was cleared on the copy, but the per-culture published
info (mapped to umbracoDocumentCultureVariation.published) was carried
over from the source. This left the database in an inconsistent state
where the document was unpublished overall but each culture row
reported published=1.
Clear PublishCultureInfos on both the root copy and its descendants
alongside the existing Published=false assignment so no culture
variations are persisted as published on the copy.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Address review feedback: use ClearPublishInfos() helper + add recursive test
- Replace direct property assignment with the existing ClearPublishInfos()
extension method for semantic clarity and consistency with UnpublishCulture.
- Rename test to match the Can_Copy_* convention used by neighbouring tests.
- Add a second test that exercises the recursive descendant path, confirming
per-culture published flags are also cleared on descendants.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Updates integration tests to explicitly verify the fix.
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* fix: prevent open redirect in public surface controllers by validating RedirectUrl with Url.IsLocalUrl
* Update src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Web.Website/Controllers/UmbProfileController.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Web.Website/Controllers/UmbRegisterController.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
Revert "Dependencies: Upgrade NUnit and related test dependencies to latest major versions (#22155)"
This reverts commit 7014f9a125 on v18/dev
to resolve the Part3Of4 SQL Server integration test nightly hangs that
started around 2026-04-10.
Root cause was confirmed by hang-dump analysis: a sync-over-async call
in ContentCacheRefresher.HandleMemoryCache
(.GetAwaiter().GetResult() on an async cache method) that NUnit 3's
pumping synchronization context had been quietly completing on the test
thread. NUnit 4 dropped that behaviour, so the continuation now requires
a free thread-pool thread; under CI conditions it deadlocks.
Reverting #22155 on a branch was verified to make the nightly pass.
This is a temporary rollback to unblock v18; the proper fix is to make
ContentCacheRefresher.Refresh async end-to-end, tracked separately.
Additional adjustments beyond the pure revert to keep the branch
compiling:
- CoreConfigurationHttpTests.cs: added `using Umbraco.Cms.Core.Services;`
for IUserService (referenced by post-#22155 code unaffected by the
revert).
- ContentVersionCleanupServiceTest.cs: merged imports so both
AutoFixture.NUnit3 (from revert) and Microsoft.Extensions.Options
(from unrelated later commit) stay.
- UdiTests.cs and ContentPermissionResourceTests.cs: removed unused
`using NUnit.Framework.Legacy;` (namespace introduced in NUnit 4).
- BackOfficeAuthorizationInitializationMiddlewareTests.cs: replaced
`[CancelAfter(5000)]` with its NUnit 3 equivalent `[Timeout(5000)]`.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Correct logging and swallowing of exceptions when retrieving references with changed property types.
* Addressed code review feedback.
* Change multi URL picker to fall back to returning an empty collection if the links JSON could not be deserialised.
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Defensively handle case where published status in databse is corrupt.
* Addressed code review feedback.
* Further code review feedback.
* Similar fix for NRE in rebuild of document URLs.
* Add option for rebuild following content type update in the background.
* Add integration test for deferred rebuild.
* Addressed code review feedback.
* add retry and graceful shutdown to deferred cache rebuild.
* Prevent shared DB connection in deferred rebuild background task.
* Move deferred rebuild trigger to post-scope notification.
* Introduce similar deferred behaviour for Examine reindexing.
* Prevent background cache rebuild from blocking foreground content saves.
* Handle potential case of primary key constraint violation when deferred rebuilding content cache and a content item is saved.
* Improved variable naming.
* Add migration to fix data type storage for labels configured with a long string value type.
* Fixed class name and added additional test from code review feedback.
* Further code review feedback.
* Add further test.
* Support separate database DbContexts in AddUmbracoDbContext.
* update internal callers to use new non-obsolete AddUmbracoDbContext overload
- UmbracoEFCoreComposer now calls the new overload with explicit shareUmbracoConnection: true
- Add #pragma CS0618 suppression for v18-obsolete overloads delegating to v19-obsolete overloads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update further internal caller to use non-obsolete method.
* Addressed code review feedback.
* Updates after merge/final local review.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Optimize ContentTypeRepository to avoid unnecessary deep-cloning on cache reads.
* Used lightweight benchmark and addressed code review comments.
* Optimize TemplateRepository to avoid unnecessary deep-cloning on cache reads.
* Optimize DomainRepository to avoid unnecessary deep-cloning on cache reads.
* Optimize remaining repositories to avoid unnecessary deep-cloning on cache reads.
* Present dialog for further action after creating an API user.
* Addressed code review feedback.
---------
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
The allowlist referenced mcp__github__create_issue_comment, which
doesn't exist in github-mcp-server v0.17.1 (the tool is
add_issue_comment). Claude's attempts to comment were denied, so
duplicates were labelled but no explanation comment was posted.
Also adds a workflow_dispatch trigger with an issue_number input and
enables show_full_output so future denials are visible in logs.
* eslint rule for Manifest Aliases
* update to handle propertyEditorSchema aliases
* make typescript check
* support localization alias
* Make consts for theme manifests
* no rules for themes
* fix not used, double media-type-root manifest, clean up.
* Improve pascal cases test
* Models, service, repository and migration for external members.
* Integrate identity for external members in MemberUserStore.
* When autolinking external member, skip member type.
* Populate profile.
* Revoke member tokens for delivery API for external members.
* Audit notification handling.
* Management API updates for external members.
* Added IMemberFilterService for combined member queries from management API.
* Referenced by member controller with external members.
* Guard password reset for external members.
* Remove ExternalMemberSettings.
* Convert between content and external members.
* Fixed ambiguous constructor.
* Update OpenApi.json.
* Update client SDK.
* Backoffice ui for external members.
* Refactor member collection retrievel to use presentation factory.
Fixes in testing.
* Fixes from testing.
* Fix icon display on member picker.
* Add external member support to member picker value converter.
* Delete fix, sync data fix, Examine indexing, member collection default icon.
* Add cache refreshers for external members.
* Remove unused "fast path" for just updating login properties.
* Addresed code review feedback.
* Further integration tests.
* Fixed failing unit test.
* Update typed client.
* Addressed code review feedback.
* Early return to reduce nesting in ReferencedByMemberController.
* Introduce MemberPresentationService and MemberReferenceService to move logic out of controllers.
* Test for and fix SQLite deadlock related to cross-store uniqueness checks.
* Additional fix for the "content" member creation.
* Defer external member Examine indexing via the background task queue.
* Add update date to external member record (aligning with content members).
* Add TreatLoginAsMemberUpdate config so member re-index can be skipped on login.
* Add logging to help verify the indexing path chosen on login and register.
* Move ExternalMemberService into Core to align with MemberService.
* Fix deserialization issue with Json payloads.
* Display of external member profile data in backoffice.
* Fixed breaking change.
* Consider existing behaviour of bumping update date on login to be a bug, so no need for configuration and backward compatibility efforts.
* Reduce user start node tree filtering code duplication
Extract shared start node filtering logic from UserStartNodeTreeControllerBase
into a dedicated service hierarchy (IUserStartNodeTreeFilterService and
domain-specific implementations for documents and media).
Existing constructor signatures and protected members are preserved as
obsolete to maintain backward compatibility for external consumers.
* Disambiguate DI constructor resolution for tree controllers
Adds obsolete constructors accepting both the legacy dependencies and the new IDocument/IMediaStartNodeTreeFilterService to the eight concrete tree controllers and to MediaTreeControllerBase. These serve as a superset constructor that lets the DI container unambiguously resolve a single constructor, since the new and existing obsolete constructors have non-subset parameter sets and [ActivatorUtilitiesConstructor] is not honoured by CallSiteFactory at ServiceProvider validation time.
* Address review feedback
- Change constructors on DocumentStartNodeTreeFilterService and
MediaStartNodeTreeFilterService from public to internal (classes are
already internal).
- Add [EditorBrowsable(Never)] to the disambiguation constructors so
IDEs hide them from autocomplete.
- Add inline comments explaining the empty-array fallback in the
obsolete GetUserStartNodeIds/GetUserStartNodePaths overrides.
* Revert filter service constructors to public
DI container requires public constructors for activation, even on
internal classes. Reverts the internal change from the previous commit.
* Add unit tests for UserStartNodeTreeFilterService
Tests ShouldBypassStartNodeFiltering (root access, data type ignore,
no access), MapWithAccessFiltering (access/no-access/missing entities),
and delegation to IUserStartNodeEntitiesService for root, child and
sibling filtering including mixed access scenarios.
* Simplify obsolete-ctor path on document and media tree controllers (#22546)
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Removed line clamp for data type picker
* Removed line clamp on additional labels
---------
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
* add users section into user group
* fix test failed
* fix unchange issue
* add notification
* add remainging count
* update take 100
* split user list into separate element
* add localization for text
* add repository for user list in user group
* update key message
* remove remainingCount from user-input
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Added early steps of member auth
* Cleaned up
* Cleaned up again
* Cleaned up
* Fixes based on comments
* Updated name of helper
* Reverted to old smokeTest command
* Emit relation saved and deleted notification when automatic relations are added and removed during content updates.
* Addressed code review feedback.
* swapping from column to row
* adds same look for when you upload image on a content node
* Remove duplicated css property
---------
Co-authored-by: engjlr <enl@umbraco.dk>
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
* Avoid requirement for IBackOfficeStore registrations for non-backoffice configured setups.
* Apply same update to other read method potentially called from non backoffice setups.
* Remove comment.
* Preserve GetUserById upgrade fallback; strengthen test assertions
- Add IRuntimeState to UserService and mirror the DbException catch
from BackOfficeUserStore.GetAsync(int) in GetUserById, so the
upgrade-time fallback to GetForUpgrade is preserved.
- Use non-empty arguments in the delivery-only integration test so
the repository-backed code paths are actually exercised, not just
the early-return guards.
- Update UserServiceCrudTests to pass IRuntimeState to the new
constructor parameter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Introduce IBackOfficeUserReader to avoid code duplication for user read methods between UserService and BackOfficeUserStore.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Implement ElementCacheService with HybridCache backing and database cache support
Fully implements ElementCacheService as the elements equivalent of DocumentCacheService,
backed by Microsoft HybridCache (L1 in-memory + L2 distributed) with database cache table
persistence via cmsContentNu.
Key changes:
- ElementCacheService: full implementation with HybridCache, draft/published separation,
converted element L0 cache, cache tagging, preview service support, and seeding infrastructure
- IDatabaseCacheRepository: added element CRUD methods (Get/Refresh/Rebuild) with SQL queries
using ElementDto/ElementVersionDto
- IContentCacheService: extracted common base interface shared by Document, Media and Element
cache services (8 shared methods including Seed, Rebuild, memory cache operations)
- CacheRefreshingNotificationHandler: added element notification handling, content type changes
now route to element or document service based on IsElement, refactored to single-pass
classification with shared RefreshCacheForContentTypeChanges method
- ElementRefreshNotification: new notification wired to ElementRepository.OnUowRefreshedEntity
- Renamed document-specific methods for clarity (GetContentSource -> GetDocumentSource,
RefreshContent -> RefreshDocument, CreateContentNodeKit -> CreateDocumentNodeKit,
RebuildContentDbCache -> RebuildDocumentDbCache)
- Renamed shared DTOs (CacheRebuildDocumentDto -> CacheRebuildPublishableContentDto) since
they're used by both documents and elements
- Extracted shared RebuildPublishableDbCache method to eliminate duplication between document
and element rebuild logic
* Add element navigation service, publish status tracking, and breadth-first seeding
Adds the infrastructure needed for element cache seeding:
- ElementNavigationService: provides tree traversal for elements, following the
same pattern as DocumentNavigationService/MediaNavigationService
- Split PublishStatusService into an abstract base class with DocumentPublishStatusService
and ElementPublishStatusService subclasses, each with their own interfaces
(IDocumentPublishStatusQueryService, IElementPublishStatusQueryService, etc.)
- ElementBreadthFirstKeyProvider: seeds the element cache on startup by traversing
the element tree breadth-first, filtering out unpublished elements
- Element publish status is initialized on startup and kept in sync via
ElementCacheRefresher
- Old IPublishStatusQueryService/IPublishStatusManagementService interfaces kept
as obsolete for backward compatibility
- Non-breaking constructor changes for ContentCacheRefresher, DocumentUrlService,
ApiContentRouteBuilder via obsolete constructor overloads
* Fix element CacheNodeFactory to set IsDraft from preview parameter
CacheNodeFactory.ToContentCacheNode(IElement, bool preview) was hardcoding
IsDraft = false instead of using the preview parameter. This caused
RefreshElementAsync to never write draft cmsContentNu rows, because
DatabaseCacheRepository.RefreshElementAsync skipped the draft write when
IsDraft was false.
* Use ElementTree lock instead of ContentTree in ElementCacheService
RefreshMemoryCacheAsync was using Constants.Locks.ContentTree instead of
Constants.Locks.ElementTree for the read lock.
* Add ElementCacheServiceTests and fix PublishStatusServiceTests for abstract base
- ElementCacheServiceTests: 9 integration tests covering draft/published retrieval,
rebuild, delete, and RefreshElementAsync behavior
- Updated PublishStatusServiceTests to use DocumentPublishStatusService instead of
the now-abstract PublishStatusService
* Add IPublishedElementCache facade for public element cache access
Introduces the public-facing element cache interface and implementation,
following the same pattern as IPublishedContentCache/IPublishedMediaCache.
- IPublishedElementCache: async-only interface (no legacy sync methods)
- ElementCache: facade delegating to IElementCacheService
- Added Elements property to ICacheManager, IUmbracoContext, and their
implementations
* Add ElementHybridCacheTests and ElementHybridCacheElementTypeTests
Integration tests exercising the full element cache pipeline via
IPublishedElementCache:
ElementHybridCacheTests (7 tests):
- Draft/published retrieval by key
- Unpublished element not accessible without preview
- Draft of published element accessible
- Updated draft element reflects changes
- Deleted element removed from cache
- Element name accessible
ElementHybridCacheElementTypeTests (3 tests):
- Structural type change removes property from cached element
- Non-structural type change preserves property values
- Element removed from cache when element type is deleted
* Fix element navigation to include containers and support breadth-first seeding
The element tree contains both elements and containers (folders) with different
object types. The navigation service now queries both object types to build
the full tree hierarchy.
- Added multi-objectType overloads to INavigationRepository and
ContentNavigationRepository using LEFT JOIN to support nodes without
content rows (containers)
- Single-objectType methods now delegate to the multi-objectType implementation
- ElementNavigationService queries both Element and ElementContainer object types
- ElementBreadthFirstKeyProvider traverses containers without seeding them,
only counting published elements toward the seed limit
- Added ElementBreadthFirstKeyProviderTests (9 tests) including container
traversal scenarios
* Add ElementContentTypeSeedKeyProvider for content-type-based element seeding
Seeds elements whose content types match the configured CacheSettings.ContentTypeKeys,
mirroring the existing ContentTypeSeedKeyProvider for documents. Both providers read
from the same configuration list — document type keys seed documents, element type
keys seed elements.
* Fix ContentNavigationServiceTest mocks for multi-objectType repository overload
The single-type GetContentNodesByObjectType(Guid) now delegates to the
multi-type overload. Updated test mocks to match the IEnumerable<Guid>
signature, verifying exactly one key containing Constants.ObjectTypes.Document.
* Skip Cannot_Get_Published_Again_After_Trashing test
Trashing does not clear the published cache — this is a pre-existing issue
that also affects documents. When a cached item is trashed, the HybridCache
entry remains because RefreshMemoryCacheAsync does not remove entries when
the database returns null for trashed items.
* Replace unsafe casts with StaticServiceProvider in obsolete constructors
The obsolete constructors in ApiContentRouteBuilder and DocumentUrlService
were using direct casts from IPublishStatusQueryService to
IDocumentPublishStatusQueryService, which would fail at runtime for
external consumers compiled against pre-v18 binaries. Use
StaticServiceProvider.Instance.GetRequiredService instead, consistent
with the pattern in ContentCacheRefresher.
* Remove duplicate XML doc summary in GetElementCultureDataForNodes
* Add obsolete constructors for backward compatibility
Preserve the old constructor signatures for CacheManager,
NavigationInitializationNotificationHandler, and
PublishStatusInitializationNotificationHandler so that external
consumers compiled against pre-element-cache versions don't break.
New dependencies are resolved via StaticServiceProvider.
* Pass cancellationToken to ExistsAsync in ElementCacheService.SeedAsync
* Fix DocumentUrlServiceTests to use IDocumentPublishStatusQueryService
* Trigger Build
* Address PR review feedback
- Rename HandlePublishedAsync to HandlePublishStatusAsync in
ContentCacheRefresher for consistency with ElementCacheRefresher
- Make ElementCacheRefresher.HandlePublishStatusAsync async to align
with ContentCacheRefresher's pattern
- Replace inline comments with #region blocks in IDatabaseCacheRepository
- Fix double enumeration in DocumentCacheService.SeedAsync and
ElementCacheService.SeedAsync by materializing to List before logging
* Invalidate element cache entries when trashed
Apply the same fix from #22451 (documents/media) to elements:
- ElementCacheService.RefreshElementAsync: early-return for trashed
elements, deleting from the database cache and removing from memory.
- ElementCacheService.RefreshMemoryCacheAsync: add symmetric else
branches so memory cache entries are removed when the database cache
has no corresponding draft or published node (self-healing).
- Re-enable Cannot_Get_Published_Again_After_Trashing integration test.
* Move element trash cache tests to ElementHybridCacheTests
Move Cannot_Get_Trashed_As_Published and
Cannot_Get_Published_Again_After_Trashing from
ElementPublishingServiceTests to ElementHybridCacheTests where they
belong — these test cache invalidation, not publishing behavior.
Add Cannot_Get_Published_Elements_After_Folder_Trashed to verify that
trashing an element folder clears its child elements from the published
cache.
* Add element hybrid cache variant tests
Add ElementHybridCacheVariantsTests covering culture variant behavior
for the element cache: variant property values per culture, invariant
property consistency across cultures, single culture updates, single
culture publishing, and draft access to both cultures.
Add isElement parameter to
CreateContentTypeWithTwoPropertiesOneVariantAndOneInvariant to support
creating variant element types without a separate builder method.
* Rename IPublishedElementCache.GetByIdAsync to GetByKeyAsync
Align with the codebase convention where Id refers to integer
identifiers and Key refers to GUID identifiers.
* Align IDocumentPublishStatusQueryService method names with element equivalent
Add IsPublished and IsPublishedInAnyCulture to
IDocumentPublishStatusQueryService to match
IElementPublishStatusQueryService naming.
Keep IsDocumentPublished and IsDocumentPublishedInAnyCulture as obsolete
default implementations delegating to the new methods, since
IPublishStatusQueryService (which exposes these names) ships on main.
Update all internal callers to use the new names.
* Keep INNER JOIN for document/media navigation queries
Only use LEFT JOIN when the query includes container types (e.g.
element containers) which don't have umbracoContent rows. Documents
and media always have content rows, so INNER JOIN preserves query
optimizer hints for those queries.
* Consolidate breadth-first seed key provider logic into base class
Make GetSeedKeys virtual on BreadthFirstKeyProvider and introduce
ShouldSeed and ShouldTraverseChildren hooks so subclasses only need
to override filtering logic instead of duplicating the entire
traversal.
- Document: overrides ShouldSeed to filter unpublished nodes
- Element: overrides ShouldSeed + ShouldTraverseChildren (always
traverse, since containers may have published children)
- Media: uses base defaults (seed and traverse everything)
Removes the 'new' hiding pattern and the V16 TODO.
* Revert "Rename IPublishedElementCache.GetByIdAsync to GetByKeyAsync"
This reverts commit 139d66776f.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Fix branch authorization from requiring recycle bin permission.
* Use named parameters.
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* fix(api): resolve correct old version on upgrade screen (closes#20980)
The upgrade screen always showed the first version of the current major
(e.g. 17.0.0) regardless of the actual database state. This was because
UpgradeSettingsFactory constructed OldVersion from just the running
app's major version number.
The fix adds UmbracoPlan.GetVersionForState() which walks the migration
transition chain and extracts version numbers from migration type
namespaces (V_{major}_{minor}_{patch} convention). RuntimeState calls
this during startup and exposes the result via a new
IRuntimeState.CurrentMigrationVersion property (with a default null
implementation to avoid breaking changes). UpgradeSettingsFactory uses
this resolved version with a fallback to the previous behaviour.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(api): return 9.4.0 for InitialState in GetVersionForState
InitialState is the final migration state of 9.4 (the lowest supported
upgrade). Returning null caused the fallback to show <major>.0.0 for
databases at that state. Now correctly resolves to 9.4.0.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore(infrastructure): add TODO (V18) to update initialVersion when InitialState changes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Added TODO for 18.
* Addressed code review feedback.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Allow packages and hosted services to set an ambient backoffice identity via AsyncLocal for scenarios where no HttpContext is available.
* Addressed code review feedback.
* Avoid allocating a string if _publishedContentCache has a cached version & removed preview param, it was always false
* Clarified comment, used GetCacheKey method from location where string was being created.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Use GeneratedRegex instead of generating at runtime
* Add unit tests to verify refactored code.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* update npm dependencies for v17.4.0 minor release
* update dependencies package
* fix lint errors
* remove Dribbble from lucide to simple icons
* revert @hey-api/openapi-ts bump
* chore: regenerate sdk.gen.ts
* chore: regenerate msw sw
* chore: regenerate icons
* build: excludes "mocks/tools" from being compiled
it is an isolated project and so can be used independent of the backoffice
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
* Propagate tree context's additional request args to tree item children, ensuring tree item children respect the "ignore user start nodes" data type setting for content pickers.
* Add unit tests for additional request args forwarding to tree item children manager.
* extend icons with information from theseaurus
* implement new icon search logic
* clean-up data
* sorting with a backup of the name
* refactor into a controller
* improve multi word group search
* embed lucide data
* rename tech into technology
* remove paper from dollar
* upgrade msw, migrate all interceptors, and update backoffice integration
* Fix msw test runner integration
* wip mock sets
* align news mock data
* clean up
* add interface for mock sets
* Refactor mock DBs to use dataSet directly
* export as data
* align exports
* Update index.ts
* simplify
* remove createTemplateScaffold from data set
* remove getGroupByName from mock set
* remove getGroupWithResultsByName from mock set
* remove getIndexByName from mock set
* remove unused getSearchResultsMockData function
* Add kenn mock data set with SQLite transformation scripts
Introduces a new "kenn" mock data set generated from an Umbraco SQLite database export.
Transformation scripts (devops/sqlite-to-mock/):
- Database connection helper using sql.js
- Transform scripts for data-types, document-types, media-types, documents, media, users, templates, languages, and dictionary
Generated kenn data set includes:
- 156 data types
- 48 document types with properties, containers, and compositions
- 11 media types
- 41 documents with property values and variants
- 75 media items
- 4 users and 6 user groups
- 10 templates, 2 languages, 5 dictionary items
Usage: VITE_MOCK_SET=kenn npm run dev
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix Tab/Group container type mapping in document types
The PropertyGroupType enum in Umbraco.Core defines:
- Group = 0
- Tab = 1
The transformer had this inverted. Fixed the mapping and regenerated
document-type.data.ts with correct container types.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix user group fallbackPermissions in transformer
Read permissions from umbracoUserGroup2Permission table instead of
the empty userGroupDefaultPermissions column. Also handles mapping
legacy single-letter permission codes to new Umb.Document.* format.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Remove deprecated createTemplateScaffold from template transformer
This function was removed from the UmbMockDataSet interface.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Move sqlite-to-mock script to main package.json
Consolidate the SQLite transformation tooling into the main package by:
- Adding sql.js, @types/sql.js, and tsx as devDependencies
- Adding sqlite-to-mock script that runs transformations and lints output
- Removing the separate devops/sqlite-to-mock/package.json and lock file
This allows the transformation scripts to reuse the main node_modules.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* add url manager and url handlers
* Add CLI parameters to sqlite-to-mock script
The script now requires db-path and set-alias arguments:
npm run sqlite-to-mock -- <db-path> <set-alias>
Changes:
- Add configure(), getDatabase(), getOutputDir(), closeDatabase() for lazy init
- Add CLI argument parsing with validation
- Remove direct execution calls from transform scripts
- Move eslint formatting into the script
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Generate complete mock data sets and auto-discover sets
- Add generate-supporting-files.ts to create index.ts and all
placeholder/static files needed for a complete mock data set
- Use import.meta.glob for dynamic mock set discovery instead
of hardcoded switch statement
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add mock handler for document type configuration
Introduces a new mock handler to serve document type configuration data, updates the mock database to provide configuration, and integrates the handler into the document type mock handlers.
* make all mock data optional
* Add custom service worker to bypass static asset requests
Introduces umbServiceWorker.js to intercept and bypass static asset requests before reaching MSW, improving startup performance in Vite development.
* fix type errors
* Update template-query.manager.ts
* change to runtime load of mock data
* Update package-lock.json
* wip mock set switcher
* Use umbMockManager.availableSetNames in mock header
* remove the test set
* clean up
* move mock files to the client project root
* rename folder
* move sqllite tool into mocks folder
* clean up
* rename folder
* update the correct tsconfig file
* Update README.md
* fix path
* mock search
* add mocks for tree siblings endpoint
* add mocks for document type and media type allowed parents
* split user permissions mock data into its own mock set
* Initialize localization registry in date test
* don't use consts. Inits too much from the modules
* Update property-editor-ui-user-picker.test.ts
* Update property-value-cloner-block-grid.cloner.test.ts
* add custom permission
* make test check for custom permission in specific mock set
* use specific mock set with specific user id
* Update document-user-permission.condition.test.ts
* Update section-user-permission.condition.test.ts
* add mock manager util to internal utils
* add import map to test runner
* Move mock-data-set.types and update imports
* Exclude internal consts in export test
* Rename mock key to userPermissions
* Register mock manifests only in development
* manual merge
* Add labels and alias/label list for mock sets
* Add visibility flag for mock sets
* delete kenn mock set
* Update mock-manager.ts
* fix(mocks): correct document type composition generation in sqlite-to-mock
The compositions were reversed - grouped by parentContentTypeId instead
of childContentTypeId. In cmsContentType2ContentType, the parent is the
composed type and the child is the type using it. Also adds inheritance
vs composition detection based on umbracoNode parentId matching.
* Update src/Umbraco.Web.UI.Client/mocks/msw-handlers/member-type/structure.handlers.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/mocks/tools/sqlite-to-mock/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/mocks/db/template-detail.manager.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix mock DB slice and add safety checks
* Adds "Kitchen Sink" mock data set
* Updates to sqlite-to-mock tool
* Default mock data set tweaks
Replaces "loremflickr.com" images with local placeholders
* "Kitchen Sink" mock data updates
* feat(mocks): add member support to sqlite-to-mock tool
Add transformers for members, member types, and member groups to replace
the empty placeholder arrays. Queries cmsMember, cmsMemberType, and
cmsMember2MemberGroup tables for auth data, property visibility, and
group relationships.
* Updated "Kitchen Sink" mock data with Members
* fix(mocks): type rawData in composition-mapped files to avoid never[] inference
When all compositions arrays are empty, TypeScript infers the element
type as never, causing a type error on the .map() callback. Adding an
explicit type annotation for rawData resolves this. Also fixed in both
generators so future runs produce correctly typed output.
* feat(mocks): implement imaging resize URLs handler
Extract the umbracoFile src from media items and build resize URLs with
width, height, mode, and format query parameters. Replaces the empty
urlInfos placeholder.
* Updated placeholder images
* fix(mocks): return actual media file URLs and add missing folders endpoint
The /media/urls handler was returning ancestor-based slug paths instead
of the umbracoFile source path, causing the image cropper modal to
render a generic file preview instead of an image preview.
Also adds the missing /item/media-type/folders handler that was causing
a crash when opening the media picker.
* fix(mocks): parse JSON values stored in varcharValue column
Short JSON values like Color Picker data are stored in varcharValue
rather than textValue in SQLite. The transformers only attempted
JSON.parse on textValue, leaving varcharValue as raw strings. Now also
parses varcharValue when it starts with { or [.
Also fixes the kitchen-sink Color Picker mock data to use parsed objects.
* fix(mocks): add missing document audit log handler
Adds a handler for GET /document/{id}/audit-log that returns the shared
audit log data from the mock data set. Prevents crash in the document
workspace info view history component.
* Mock data tweaks
* move logic from msw handlers to mock services
* remove debugger
* introduce an audit log db class
---------
Co-authored-by: Mads Rasmussen <madsr@hey.com>
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* adds same drag styling as when dragging item in the content sectin
* remove unused loader css
---------
Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
Pass `github_token` and set `allowed_non_write_users: "*"` so the action
bypasses the OIDC actor check, which rejects non-maintainers with
"User does not have write access on this repository". Safe here because
`permissions:` and `--allowedTools` are tightly scoped to issue ops.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* upgrade msw, migrate all interceptors, and update backoffice integration
* Fix msw test runner integration
* wip mock sets
* align news mock data
* clean up
* add interface for mock sets
* Refactor mock DBs to use dataSet directly
* export as data
* align exports
* Update index.ts
* simplify
* remove createTemplateScaffold from data set
* remove getGroupByName from mock set
* remove getGroupWithResultsByName from mock set
* remove getIndexByName from mock set
* remove unused getSearchResultsMockData function
* Add kenn mock data set with SQLite transformation scripts
Introduces a new "kenn" mock data set generated from an Umbraco SQLite database export.
Transformation scripts (devops/sqlite-to-mock/):
- Database connection helper using sql.js
- Transform scripts for data-types, document-types, media-types, documents, media, users, templates, languages, and dictionary
Generated kenn data set includes:
- 156 data types
- 48 document types with properties, containers, and compositions
- 11 media types
- 41 documents with property values and variants
- 75 media items
- 4 users and 6 user groups
- 10 templates, 2 languages, 5 dictionary items
Usage: VITE_MOCK_SET=kenn npm run dev
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix Tab/Group container type mapping in document types
The PropertyGroupType enum in Umbraco.Core defines:
- Group = 0
- Tab = 1
The transformer had this inverted. Fixed the mapping and regenerated
document-type.data.ts with correct container types.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix user group fallbackPermissions in transformer
Read permissions from umbracoUserGroup2Permission table instead of
the empty userGroupDefaultPermissions column. Also handles mapping
legacy single-letter permission codes to new Umb.Document.* format.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Remove deprecated createTemplateScaffold from template transformer
This function was removed from the UmbMockDataSet interface.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Move sqlite-to-mock script to main package.json
Consolidate the SQLite transformation tooling into the main package by:
- Adding sql.js, @types/sql.js, and tsx as devDependencies
- Adding sqlite-to-mock script that runs transformations and lints output
- Removing the separate devops/sqlite-to-mock/package.json and lock file
This allows the transformation scripts to reuse the main node_modules.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* add url manager and url handlers
* Add CLI parameters to sqlite-to-mock script
The script now requires db-path and set-alias arguments:
npm run sqlite-to-mock -- <db-path> <set-alias>
Changes:
- Add configure(), getDatabase(), getOutputDir(), closeDatabase() for lazy init
- Add CLI argument parsing with validation
- Remove direct execution calls from transform scripts
- Move eslint formatting into the script
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Generate complete mock data sets and auto-discover sets
- Add generate-supporting-files.ts to create index.ts and all
placeholder/static files needed for a complete mock data set
- Use import.meta.glob for dynamic mock set discovery instead
of hardcoded switch statement
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add mock handler for document type configuration
Introduces a new mock handler to serve document type configuration data, updates the mock database to provide configuration, and integrates the handler into the document type mock handlers.
* make all mock data optional
* Add custom service worker to bypass static asset requests
Introduces umbServiceWorker.js to intercept and bypass static asset requests before reaching MSW, improving startup performance in Vite development.
* fix type errors
* Update template-query.manager.ts
* change to runtime load of mock data
* Update package-lock.json
* wip mock set switcher
* Use umbMockManager.availableSetNames in mock header
* remove the test set
* clean up
* move mock files to the client project root
* rename folder
* move sqllite tool into mocks folder
* clean up
* rename folder
* update the correct tsconfig file
* Update README.md
* fix path
* mock search
* add mocks for tree siblings endpoint
* add mocks for document type and media type allowed parents
* split user permissions mock data into its own mock set
* Initialize localization registry in date test
* don't use consts. Inits too much from the modules
* Update property-editor-ui-user-picker.test.ts
* Update property-value-cloner-block-grid.cloner.test.ts
* add custom permission
* make test check for custom permission in specific mock set
* use specific mock set with specific user id
* Update document-user-permission.condition.test.ts
* Update section-user-permission.condition.test.ts
* add mock manager util to internal utils
* add import map to test runner
* Move mock-data-set.types and update imports
* Exclude internal consts in export test
* Rename mock key to userPermissions
* Register mock manifests only in development
* manual merge
* Add labels and alias/label list for mock sets
* Add visibility flag for mock sets
* delete kenn mock set
* Update mock-manager.ts
* fix(mocks): correct document type composition generation in sqlite-to-mock
The compositions were reversed - grouped by parentContentTypeId instead
of childContentTypeId. In cmsContentType2ContentType, the parent is the
composed type and the child is the type using it. Also adds inheritance
vs composition detection based on umbracoNode parentId matching.
* Update src/Umbraco.Web.UI.Client/mocks/msw-handlers/member-type/structure.handlers.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/mocks/tools/sqlite-to-mock/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/mocks/db/template-detail.manager.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix mock DB slice and add safety checks
* webhook mock plan
* init webhook mock set + handlers
* Adds "Kitchen Sink" mock data set
* Updates to sqlite-to-mock tool
* Default mock data set tweaks
Replaces "loremflickr.com" images with local placeholders
* "Kitchen Sink" mock data updates
* Add paginated list and remove collection handler
* feat(mocks): add member support to sqlite-to-mock tool
Add transformers for members, member types, and member groups to replace
the empty placeholder arrays. Queries cmsMember, cmsMemberType, and
cmsMember2MemberGroup tables for auth data, property visibility, and
group relationships.
* Updated "Kitchen Sink" mock data with Members
* fix(mocks): type rawData in composition-mapped files to avoid never[] inference
When all compositions arrays are empty, TypeScript infers the element
type as never, causing a type error on the .map() callback. Adding an
explicit type annotation for rawData resolves this. Also fixed in both
generators so future runs produce correctly typed output.
* Add webhook delivery mock data and handlers
* Add webhook event mock data and handlers
* include webhooks in kitchen sink data set
* Add flags to webhook mock; fix item response
* Support pagination in webhook events handler
* Update src/Umbraco.Web.UI.Client/mocks/db/webhook-delivery.db.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update detail.handlers.ts
* Map webhook event aliases to event objects
* remove note about being created from SQL db
---------
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Co-authored-by: leekelleher <leekelleher@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* TipTap: Declare Clear Formatting toolbar button's extension dependencies
* Reworked to have a loose dependency
on the `class` and `style` attribute extensions
---------
Co-authored-by: leekelleher <leekelleher@gmail.com>
* Eliminate closure, fix naming & formatting of exceptions
* Added unit tests around the changed code.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Use configured or detected application URL as request URL fallback in background tasks when constructing absolute URLs.
* Addresed code review feedback.
* upgrade msw, migrate all interceptors, and update backoffice integration
* Fix msw test runner integration
* wip mock sets
* align news mock data
* clean up
* add interface for mock sets
* Refactor mock DBs to use dataSet directly
* export as data
* align exports
* Update index.ts
* simplify
* remove createTemplateScaffold from data set
* remove getGroupByName from mock set
* remove getGroupWithResultsByName from mock set
* remove getIndexByName from mock set
* remove unused getSearchResultsMockData function
* Add kenn mock data set with SQLite transformation scripts
Introduces a new "kenn" mock data set generated from an Umbraco SQLite database export.
Transformation scripts (devops/sqlite-to-mock/):
- Database connection helper using sql.js
- Transform scripts for data-types, document-types, media-types, documents, media, users, templates, languages, and dictionary
Generated kenn data set includes:
- 156 data types
- 48 document types with properties, containers, and compositions
- 11 media types
- 41 documents with property values and variants
- 75 media items
- 4 users and 6 user groups
- 10 templates, 2 languages, 5 dictionary items
Usage: VITE_MOCK_SET=kenn npm run dev
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix Tab/Group container type mapping in document types
The PropertyGroupType enum in Umbraco.Core defines:
- Group = 0
- Tab = 1
The transformer had this inverted. Fixed the mapping and regenerated
document-type.data.ts with correct container types.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix user group fallbackPermissions in transformer
Read permissions from umbracoUserGroup2Permission table instead of
the empty userGroupDefaultPermissions column. Also handles mapping
legacy single-letter permission codes to new Umb.Document.* format.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Remove deprecated createTemplateScaffold from template transformer
This function was removed from the UmbMockDataSet interface.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Move sqlite-to-mock script to main package.json
Consolidate the SQLite transformation tooling into the main package by:
- Adding sql.js, @types/sql.js, and tsx as devDependencies
- Adding sqlite-to-mock script that runs transformations and lints output
- Removing the separate devops/sqlite-to-mock/package.json and lock file
This allows the transformation scripts to reuse the main node_modules.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* add url manager and url handlers
* Add CLI parameters to sqlite-to-mock script
The script now requires db-path and set-alias arguments:
npm run sqlite-to-mock -- <db-path> <set-alias>
Changes:
- Add configure(), getDatabase(), getOutputDir(), closeDatabase() for lazy init
- Add CLI argument parsing with validation
- Remove direct execution calls from transform scripts
- Move eslint formatting into the script
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Generate complete mock data sets and auto-discover sets
- Add generate-supporting-files.ts to create index.ts and all
placeholder/static files needed for a complete mock data set
- Use import.meta.glob for dynamic mock set discovery instead
of hardcoded switch statement
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add mock handler for document type configuration
Introduces a new mock handler to serve document type configuration data, updates the mock database to provide configuration, and integrates the handler into the document type mock handlers.
* make all mock data optional
* Add custom service worker to bypass static asset requests
Introduces umbServiceWorker.js to intercept and bypass static asset requests before reaching MSW, improving startup performance in Vite development.
* fix type errors
* Update template-query.manager.ts
* change to runtime load of mock data
* Update package-lock.json
* wip mock set switcher
* Use umbMockManager.availableSetNames in mock header
* remove the test set
* clean up
* move mock files to the client project root
* rename folder
* move sqllite tool into mocks folder
* clean up
* rename folder
* update the correct tsconfig file
* Update README.md
* fix path
* mock search
* add mocks for tree siblings endpoint
* add mocks for document type and media type allowed parents
* split user permissions mock data into its own mock set
* Initialize localization registry in date test
* don't use consts. Inits too much from the modules
* Update property-editor-ui-user-picker.test.ts
* Update property-value-cloner-block-grid.cloner.test.ts
* add custom permission
* make test check for custom permission in specific mock set
* use specific mock set with specific user id
* Update document-user-permission.condition.test.ts
* Update section-user-permission.condition.test.ts
* add mock manager util to internal utils
* add import map to test runner
* Move mock-data-set.types and update imports
* Exclude internal consts in export test
* Rename mock key to userPermissions
* Register mock manifests only in development
* manual merge
* Add labels and alias/label list for mock sets
* Add visibility flag for mock sets
* delete kenn mock set
* Update mock-manager.ts
* fix(mocks): correct document type composition generation in sqlite-to-mock
The compositions were reversed - grouped by parentContentTypeId instead
of childContentTypeId. In cmsContentType2ContentType, the parent is the
composed type and the child is the type using it. Also adds inheritance
vs composition detection based on umbracoNode parentId matching.
* Update src/Umbraco.Web.UI.Client/mocks/msw-handlers/member-type/structure.handlers.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/mocks/tools/sqlite-to-mock/README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/mocks/db/template-detail.manager.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix mock DB slice and add safety checks
* Adds "Kitchen Sink" mock data set
* Updates to sqlite-to-mock tool
* Default mock data set tweaks
Replaces "loremflickr.com" images with local placeholders
* "Kitchen Sink" mock data updates
* feat(mocks): add member support to sqlite-to-mock tool
Add transformers for members, member types, and member groups to replace
the empty placeholder arrays. Queries cmsMember, cmsMemberType, and
cmsMember2MemberGroup tables for auth data, property visibility, and
group relationships.
* Updated "Kitchen Sink" mock data with Members
* fix(mocks): type rawData in composition-mapped files to avoid never[] inference
When all compositions arrays are empty, TypeScript infers the element
type as never, causing a type error on the .map() callback. Adding an
explicit type annotation for rawData resolves this. Also fixed in both
generators so future runs produce correctly typed output.
---------
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Co-authored-by: leekelleher <leekelleher@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix(SqliteSyntaxProvider.cs): parameterises the `tableName` variable when passing into `DoesPrimaryKeyExist` method
* fix(SqlServerSyntaxProvider.cs): parameterises the `tableName` variable when passing into the `DoesPrimaryKeyExist` sql statement
* test(DoesPrimaryKeyExist-test): Add test file for DoesPrimaryKeyExist
Co-authored-by: LLaverty <liamlaverty@gmail.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Align output cache extension points for the delivery API with those for the website.
* Fix issue running output cache on website and delivery API at the same time.
* Updates from testing.
* Align website default implementation with naming used for delivery API equivalents.
* Addressed code review feedback.
* Updates from self-review.
* Allow removal of template on a document, and indicate when the selected template is no longer allowed.
* Addressed code review feedback.
* remove duplicate inline color style on template icon
---------
Co-authored-by: engjlr <enl@umbraco.dk>
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
* Document Types: Prevent disabling isElement when elements of that type exist
Mirrors the existing document-to-element guard: switching an element type
to a document type is now blocked when elements of that type exist. Adds
ElementToDocumentHasNoContentAsync to IElementSwitchValidator and a new
ContentTypeOperationStatus.InvalidElementFlagElementHasContent mapped to
a BadRequest in the document type controller.
* Address PR review feedback for isElement guard
Extract shared HasNoContentNodesAsync helper in ElementSwitchValidator
to deduplicate DocumentToElement and ElementToDocument checks. Make
WithAllowedInLibrary conditional on isElement in test setup.
* Add end-to-end integration tests for element switch validation
Add three tests to ContentTypeEditingServiceTests that verify
UpdateAsync returns the correct operation status when element
flag changes are blocked: document-to-element with existing
content, element-to-document with existing elements, and
element-to-document when used in block structures.
* Remove default interface implementation for ElementToDocumentHasNoContentAsync
Per review feedback: custom implementations of IElementSwitchValidator are unlikely, and a default implementation hides the fact that changes to the real implementation would need to be mirrored here. Accept the small breaking change for a clearer upgrade path.
* Group get all paths to avoid exceeding SQL Server's max parameter count.
* Move GetAllPaths batching tests to dedicated test class
Move the explicit SQL Server parameter limit tests into their own
class (EntityServiceGetAllPathsTests) with NewSchemaPerTest so the
raw SqlException surfaces instead of being masked by scope disposal.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* use currentColor as color fallback
* clean up necessary prop
* Add test color behavior coverage for umb-icon
---------
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
Co-authored-by: engjlr <enl@umbraco.dk>
Fork PRs on the `pull_request` event don't have access to repository
secrets, so the action fails and surfaces a red check on the PR. Guard
the job with a head-repo equality check so the workflow simply doesn't
run for fork PRs. Remove once upstream fork support lands
(anthropics/claude-code-action#939) and `pull_request_target` can be
re-enabled.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pull_request_target fails at OIDC token exchange ("401 Unauthorized -
Invalid OIDC token") against Anthropic's backend, even though the
action itself supports the event (PR #579). Fork PRs will not be
auto-reviewed until the upstream issue is resolved. Kept the
pull_request_target block commented with a pointer to the issues
for when re-enabling becomes viable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Docs require actions:read at the workflow permissions level in addition
to additional_permissions on the action, so Claude's CI-reading MCP
tools can actually function. See anthropics/claude-code-action
docs/configuration.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(core): add member sign-in/sign-out notifications
Add MemberLoginSuccessNotification, MemberLoginFailedNotification,
and MemberLogoutSuccessNotification to achieve parity with the
existing backoffice user authentication notifications.
Override HandleSignIn in MemberSignInManager to publish login
success/failure notifications, and override SignOutAsync to publish
logout notifications. This follows the same pattern used by
BackOfficeSignInManager for backoffice users.
Closes#22461
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(core): add remarks to member auth notification classes
Add <remarks> XML documentation to MemberLoginSuccessNotification,
MemberLoginFailedNotification, and MemberLogoutSuccessNotification
describing intended usage, consistent with the backoffice user
notification equivalents.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(web): use IIpResolver for member auth notification IP addresses
Use IIpResolver.GetCurrentRequestIpAddress() for consistent IP
resolution in member auth notifications, matching the pattern used
by BackOfficeUserManager.
Introduces IIpResolver as a new constructor parameter with the
existing constructor marked obsolete (removal in Umbraco 19) using
StaticServiceProvider fallback for backwards compatibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fixed filing unit tests.
* Added tests for new functionality.
* Ensure MemberFailedNotification is fired on invalid credentials as well as member not found.
Add the reason for the failure to the notification.
* Add tests for other failed notification publishing states.
* Clarified comments.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
The client CLAUDE.md's action-to-doc table already maps deprecation
to docs/deprecation.md, and the root's callout directs agents to read
the client CLAUDE.md for backoffice work. Having the pattern in both
places is redundant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Agents working from the repo root now see an explicit instruction to
read the client's CLAUDE.md before touching backoffice code. Prevents
missing project-specific conventions (like UmbDeprecation) that are
documented in the client project but not the root.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Maps specific actions (deprecate, create element, add tests, etc.) to
the docs that MUST be read first. Ensures developers opening only the
client folder see the requirements in their Claude context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The backoffice client requires both @deprecated JSDoc AND a runtime
UmbDeprecation warning for every deprecation. This was documented in
the client's docs/deprecation.md but not referenced in the root
CLAUDE.md, causing AI agents to miss the runtime warning requirement.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Broadens the .claude gitignore to ignore everything except skills/
(committed for CI workflows) and settings.json (shared config).
Previously only settings.local.json was ignored, leaving lock files,
worktrees, and scheduled_tasks artifacts untracked but visible.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Cache: Invalidate published cache entries when content or media is trashed
Trashed content and media were remaining in the published cache because
ContentRefreshNotification/MediaRefreshNotification wrote the trashed
entities back into the cache, and ContentCacheRefresher.HandleMemoryCache
could not resolve the branch descendants after HandleNavigation had moved
them to the recycle bin.
- DocumentCacheService.RefreshContentAsync / MediaCacheService.RefreshMediaAsync:
early-return for trashed entities, deleting from the database cache and
removing from the local memory cache.
- DocumentCacheService.RefreshMemoryCacheAsync / MediaCacheService.RefreshMemoryCacheAsync:
added symmetric else branches so memory cache entries are removed when the
database cache has no corresponding draft or published node (self-healing).
- ContentCacheRefresher.HandleMemoryCache: added a bin fallback to
TryGetDescendantsKeys so broadcasted RefreshBranch payloads can resolve
descendants moved to the recycle bin on load-balanced servers.
- Integration tests covering trashed content and media cache invalidation.
* Cache: Add tests for restoring trashed content and media
Verifies that restored content is back in the draft cache (but not the
published cache, since restore does not republish) and that restored
media is back in the cache.
* Address PR review feedback
- Add bin fallback to MediaCacheRefresher.HandleMemoryCache for
consistency with ContentCacheRefresher.
- Remove redundant [Test] attributes alongside [TestCase].
* Apply suggestions from code review
Co-authored-by: Andy Butland <abutland73@gmail.com>
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
Backoffice: Add explicit controller aliases to observe() calls in tree item and default tree elements
Without explicit aliases, observe() falls back to hashing the callback's
source string on every invocation. The api setter on tree-item-element-base
and the #observeData() method on default-tree.element are called each time
the api property changes, making the hash cost and implicit deduplication
behaviour visible in hot render paths.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
Fix ElementPickerValueConverterTests build by passing IPropertyRenderingContextAccessor
The PublishedProperty constructor was updated to take an
IPropertyRenderingContextAccessor as its 4th argument, but
ElementPickerValueConverterTests was not updated, breaking the
Umbraco.Tests.UnitTests build.
pull_request events from forks cannot access OIDC tokens, causing the
job to fail. pull_request_target runs in the base repo context and has
access to secrets/OIDC while still reading the PR diff via the API.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Ensure MigrationBase formats Guids consistently with NPoco for SQLite
SQLite is case sensitive and doesn't have the concept of uniqueidentifier - Guids are stored as uppercase strings
Add FormatGuid method to SqlSyntaxProvider to centralize the logic
* (Optional) Include default FormatGuid implementation in ISqlSyntaxProvider to make this change non-breaking
* Use ToUpperInvariant for Guids in SQLite
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Tidy up comments, fix existing indentation and add unit tests for GUID formatting.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Updated tipTapSettings to match the recent changes
* Updated ui helper for insert value/dictionary/partial view button
* Updated api helper for media delivery
* Fixed api helper for verify width and height in vector graphic media
* localize rte block clipboard entry label
* RTE Block Clipboard: reuse existing localization controller
Avoids alias collision from creating a new UmbLocalizationController on
hosts that already have one. Exposes the base class controller as
protected so subclasses can reuse it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Remove obsolete TODO (already fixed to the extend possible)
* Remove irrelevant TODO
* Refactor publishable entity building from DTOs
* Fix TODO for presentation factory
* Move shared view models from Document to Content
* Clarify TODO after testing refactoring feasibility
* Update src/Umbraco.Cms.Api.Management/ViewModels/Content/ScheduleRequestModel.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Cms.Api.Management/Factories/IElementPresentationFactory.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Cleanup element TODOs in core (first take)
* Cleanup more element TODOs in PublishableContentServiceBase and ElementEditingService
* Implement Delivery API for ElementPickerValueConverter (removes TODOs and add a few new ones)
* Move the generic implementation of PublishedElementWrapped to its own class file
* Review comments for IPublishableContentRepository
* Use explicit dependency instead of access-via-casting
* Update src/Umbraco.PublishedCache.HybridCache/PublishedElement.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Add login for basic authentication without backoffice.
* Add 2FA to basic authentication flow.
* Accessibility improvements.
* Add tests for BasicAuthLoginController.
* Gate controller so only used when basic authentication is enabled.
Use 2FA view even when login page is not configured.
* Add tests for BasicAuthenticationMiddleware.
* Add support for external login providers.
* Addressed code review feedback.
* Applied suggestions from code review.
* Disable and change text on submit button when logging in.
* Add custom view support.
* Configuration for website output cache settings.
* Interfaces and default implementation for extension points.
* Configure the output cache policy.
* Evict cached documents through updates to related documents, media and members.
* Feedback from code review.
* Update description of service registration in IWebsiteOutputCacheDurationProvider header comment.
Co-authored-by: Sven Geusens <sge@umbraco.dk>
* Use output cache over service provider.
* Optimise and DRY-up eviction handlers.
* Only register IWebsiteOutputCacheManager when the feature is enabled.
* Remove unnecessary check on applying output cache to Umbraco pipeline.
* Add extension point for determining if requests should be cached.
* Broken up large method in DocumentOutputCacheEvictionHandler, put enabled checks around debug logging, further unit test.
---------
Co-authored-by: Sven Geusens <sge@umbraco.dk>
* User Service: Prevent fetching all permissions when no IDs are provided
Ensures that the UserService does not attempt to fetch permissions when the provided ID collection is empty, avoiding potentially expensive database queries that could return permissions for all nodes.
* Move guard into the shared private method and add an integration test to verify the fix.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* fixes modal text styling in Insert and Sections in Templates
* fixed review issues and added accesability for the cards so you can use keyboard
* fixing formatting changes
* fixed unused css and fixed accessability to match the card select & deselect
* fixed redundant key and click events
* fixed accessability for button and small bug with not being able to click it
* Apply language fallback to block element expose filtering.
* Handle code review feedback.
* Use builder instead of mocks in tests.
* Fixed failing unit tests.
* Revert previous approach and move fallback handling to the block property value creator.
* Include fallback policy in published property cache key
* Recreate block elements with resolved fallback culture.
* Use correct pattern for dispose.
* Introduce and use PropertyRenderingContext.
* Tidy up Fallback.
* Use core extensions for string comparison
* Less allocations
* Avoid fallback handling when no fallback policies are provided
---------
Co-authored-by: kjac <kja@umbraco.dk>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
Reflects the two-workflow split, trigger phrase stripping behavior,
allowed tools, labeling for both PRs and issues, and implementation
gotchas discovered during setup.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude couldn't find the PR because checkout is on main and
gh pr view with no args returns nothing. Now the PR number is
injected directly into the prompt from the GitHub event context.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude discovered and invoked the umb-review skill which uses git diff
against origin/main — but checkout is on main so the diff was empty.
Prompt now explicitly says to use gh pr diff, not git diff or skills.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The sandbox blocks multi-command Bash operations without approval.
Allow gh and git commands so Claude can read diffs, post comments,
and apply labels without permission errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The action strips @claude from the comment before passing to Claude,
so commands arrive as just 'review', 'fix', etc. Updated prompt to
match. Also default empty messages to review (PR) or help (issue).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prompt now reads the user's message and acts accordingly instead of
prescribing behavior. Common patterns like review/help/fix/label
are listed as examples.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude was treating @claude review as a greeting instead of acting
on the PR. Made prompt explicit about reviewing immediately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
With only opened/ready_for_review triggers, volume is low enough to
let Claude run without a turn limit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
25 turns was insufficient — the umb-review skill needs many turns to
read docs, references, changed files, and write the review.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- claude-review.yml: Auto PR review on open/push/ready (no trigger needed)
- claude.yml: Interactive — @claude comments, issue assignment/labeling
Follows anthropics/claude-code-action official examples pattern.
Full Option B gating on the interactive workflow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Only spin up a runner for issue_comment events that mention @claude.
All other event types pass through to the action for internal filtering.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merge auto and on-demand review workflows into claude-review.yml.
Add issue support via assignee_trigger and label_trigger.
Let claude-code-action handle permission gating and trigger matching.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
claude-code-action gates on write permission by default — the manual
getCollaboratorPermissionLevel check was redundant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Avoids collision with the claude-code-action bot's own @claude trigger.
Re-enables job-level filter to skip non-matching comments early.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* DevOps: Add Claude automated PR review action (closes #AB66809)
Adds two GitHub Actions workflows that run the umb-review Claude skill on every non-draft PR and on demand via `@claude review` comments. Reviews are advisory-only and post inline comments per finding plus one summary comment per review run.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* DevOps: Disable auto/on-demand triggers for initial testing
Remove pull_request_target trigger from auto workflow (workflow_dispatch only).
Disable on-demand job until auto workflow is validated.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* enables task
* adds more categories
* DevOps: Address Copilot review feedback
- Checkout PR head ref (not base) so git diff works correctly
- Use fetch-depth: 0 for triple-dot diff merge base
- Fix SHA dedup: use full SHA and paginate comment listing
- Include 'maintain' permission in on-demand gate
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Docs: Document Claude automated PR review workflows in CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
MediaBreadthFirstSeedCount was initialized with StaticDocumentBreadthFirstSeedCount
instead of StaticMediaBreadthFirstSeedCount, mismatching its [DefaultValue] attribute.
* chore(tree): remove deprecated tree store infrastructure
Remove the entire tree store pattern that was deprecated in favor of
direct tree repository queries. This deletes 29 tree store files,
removes the ManifestTreeStore extension type, updates all 15+ tree
repository constructors to remove store context token parameters,
cleans up manifests/constants/index exports, and migrates all
skip/take pagination to the paging property pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(workspace): remove deprecated methods and properties
Remove deprecated methods/properties across workspace contexts, menu
structures, tree items, and collections:
- Tree item context: getManifest(), loadMore()
- Content workspace: loadSegments()
- Entity detail workspace: parentUnique/parentEntityType observables,
getParent/setParent/getParentUnique/getParentEntityType methods,
_scaffoldProcessData (replaced by _processIncomingData)
- Menu structure contexts: #parent state, provideContext('UmbMenuStructureWorkspaceContext')
- Document/media/blueprint/member workspaces: contentTypeHasCollection,
getCollectionAlias(), getContentTypeId() (replaced by getContentTypeUnique())
- Collection context: setManifest(), getManifest() from interface and implementation
- Bulk delete action: deprecated _items getter/setter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(core): remove deprecated type aliases and exports
Remove deprecated type aliases scheduled for v18 removal:
- PackageManifestResponse (use UmbPackageManifestResponse)
- UmbSectionDefaultElement (use UmbDefaultSectionElement)
- ConditionsCollectionView (use UmbConditionsCollectionView)
- MediaValueType (use UmbMediaValueType)
- UrlParametersRecord (use UmbUrlParametersRecord)
- ActiveVariant (use UmbActiveVariant)
- UmbPropertyValueChangeEvent class and deprecated property-value-change
event listeners
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(ui): remove deprecated config and UI exports
- Textarea: remove deprecated minHeight/maxHeight config reads
- Image cropper modal: remove deprecated default export
- UFM filters: remove 3 deprecated camelCase filter manifests
(StripHtmlCamelCase, TitleCaseCamelCase, WordLimitCamelCase)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(repository): make totalAfter/totalBefore mandatory in UmbTargetPagedModel
Make totalAfter and totalBefore required properties (were optional),
fulfilling the TODO to make these mandatory in v18. All downstream
tree data sources already provide these values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: fix lint formatting
Auto-fixed formatting from lint run (line wrapping, trailing newlines).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(collection): default filter parameter in element collection repositories
The UmbCollectionRepository interface defines filter as optional.
Without a default, calling requestCollection() without arguments
would throw when accessing filter.skip/filter.take.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(backoffice): resolve ESLint errors, fix pagination metadata, and remove missed deprecations
- Remove unused UmbObjectState import (ESLint error from merge)
- Remove unused offsetPaging variable in tree-item-children.manager.ts
- Fix totalBefore/totalAfter in all tree data sources to account for skip
offset (was always reporting totalBefore: 0 regardless of skip value)
- Remove deprecated entityType property from UmbElementValueModel
(marked for v18 removal)
- Remove deprecated _items getter/setter from UmbTrashEntityBulkAction
(marked for v18 removal)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(backoffice): remove entityType references from tests and source after type removal
Remove entityType property from test fixtures and media-dropzone.manager.ts
following removal of the deprecated entityType from UmbElementValueModel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
* entity-action manifests shuffle
* feat(elements): show allowed element types in create action modal
Replace the generic document type picker with a custom create options
modal that fetches allowed element types from the library API and
displays them alongside a folder creation option, following the
established Media create pattern.
* feat(elements): add collection create action with allowed types and folder option
Add custom collection action element that fetches allowed element types
and discovers entityCreateOptionAction extensions (e.g. folder creation),
rendering them as a button or dropdown in the collection toolbar.
* refactor(elements): use dynamic entityCreateOptionAction extensions in create modals
Replace hardcoded folder option in the element create options modal with
UmbExtensionsApiInitializer to dynamically discover entityCreateOptionAction
extensions, enabling 3rd party extensibility.
* style(elements): clean up redundant state, magic strings, and empty styles
Use UMB_ELEMENT_ROOT_ENTITY_TYPE constant instead of magic string,
remove unused _headline state and empty css template, inline
single-use getter.
* fix(elements): address PR review feedback and export missing constants
- Extend UmbNamedEntityModel instead of duplicating name field
- Add getHref() support and error handling matching core patterns
- Add max-height on scroll container, icon fallbacks, element-specific
localization key
- Export UMB_ELEMENT_CREATE_OPTIONS_MODAL and
UMB_ELEMENT_TYPE_STRUCTURE_REPOSITORY_ALIAS through index chain
- Add feature parity checklist to clean-code docs
* style(elements): add noElementTypes localization entry and lint tweaks
* fix(elements): handle href navigation and error handling in create options modal
Navigate via history.pushState when href is present on create option
actions. Only close modal on successful execute, keeping it open on
failure so users can retry.
* Add temporary .skip tag to element smoke tests due to UI changes - to be fixed in another PR
---------
Co-authored-by: Nhu Dinh <150406148+nhudinh0309@users.noreply.github.com>
Co-authored-by: Nhu Dinh <hnd@umbraco.dk>
* Revert production mode validation for templates and partial views at the service layer, and move to management API.
* Remove unused ConfigureProductionMode helper from PartialViewServiceTests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add integration tests for UpdateTemplateController production mode behavior
Tests verify that the Management API correctly blocks template content
changes while allowing metadata-only updates in production mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Restore partial view service checks.
Add integration tests for template controllers with production mode.
* Align delete with create/update for file system changes in production mode.
* Restore partial view service tests.
* Add test for update to delete template repository.
* Refactored to use single test setup method.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* todo cleanup
* adding activatorUtilitiesConstructor atribute
* fix failed test by adding ActivatorUtilitiesConstructor
* Apply suggestion from @AndyButland
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Apply suggestion from @AndyButland
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Apply suggestion from @AndyButland
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Apply suggestion from @AndyButland
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Apply suggestion from @AndyButland
Co-authored-by: Andy Butland <abutland73@gmail.com>
* update umbracoPlan and remove ConfigureSecurityStampOptions
* Removed uneeded using.
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Exclude invariant culture from culture list endpoint
The Invariant Culture (CultureInfo.InvariantCulture) has an empty Name
property which is not a valid ISO code for Umbraco content. Filter it
out in IsoCodeValidator to prevent it appearing in the culture list.
Fixes#22380
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add unit tests for IsoCodeValidator.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Remove flex-shrink=0 from umb-body-layout
* Avoid collapsing tabs into the dropdown
* Add arrows left and right and bind a scroll
* Add a resizeObserver to keep track when the tabs container change
* Make the sort mode scrollable
* Move the add tab button inside the tabs list container
* Restore tab scrolling and detect hidden overflow
* Create a reusable scrollable container component
* Remove unused import
* Clean up
* Add HTMLElementTagNameMap to the scrollable container
* Always render the add tab button
* Observe slot children on slotchange
* Remove unused variable
* build(deps): bumps @umbraco-ui to 2.0.0-alpha.1 with new themes
* fix: updates paths to new themes
* feat: uses new uui themes for static cshtml files
* feat: updates to use UUISelectOption and UUIFormControlWithBasicsMixin
* build: copy all themes to "themes" folder
* build(uui): updates themes path so it works relatively with fonts
* build: updates minimum node.js version to build from 22 to 24 to support UUI
* fix: corrects paths to theme css
* docs: update CLAUDE.md files to reflect UUI 2.x for CMS v18
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(storybook): adds theme switcher
* docs(storybook): updates paths
* docs(web): document UUI theme CSS pipeline across build files
Add comments linking the files involved in UUI theme CSS handling:
- manifests.ts: where theme CSS paths are declared, with note on UUI origin
- external/uui/vite.config.ts: where themes are copied for production builds
- vite.config.ts: where themes are copied for dev server and PR previews
- copy-to-cms.js: clarifies UUI themes are already in dist-cms at this point
Each file points to the others, making the dependency on UUI theme
filenames visible without adding abstraction.
https://claude.ai/code/session_015ntS4GXa4s9BQHsjvigDh2
* Update package.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: adjusts types
* update lockfile
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
* Document patch, variant name only
* Multi variant tests
* Change to json-patch instead of merge to target nested properties
* Fix ManagementApiTest following PR 20820
* Segment suport for properties
* Verify non existing and trashed document patch behaviour
* Mostly working approuch for nested properties
* Fix endpoint route collision (Somehow...)
* Trying a custom way of doing things
* add escape support, more tests and cleanup
* remove unnecesary using
* Cleanup
* Restore things that are breaking
* cleanup
* Namespace cleanup
* Order cleanup
* More comment updates
* Add default implementations
* Improve modelbinding validation
* all string comparison
* Cleanup unused statuses
* Fix PatchPathResolver Filtering not accepting non string values
* Optimize path parsing
* Improve cookie token rework
* more cleanup
* Put AllowedValues on the correct property 🙈
* One more default implementation
* Add link to docs on endpoint swagger info
* PR review corrections
- Removed leftover affectedCultures & affectedSegments
- Extracted IDocumentPatcher interface
- Optimized serialization in patchEngine by moving it 1 level higher
* Update documentation urls
* Apply suggestions from code review
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Removed affected variance tracking that is nog longer being used
* Extract shared data class
* update claude patching namespace
* Remove no longer valid xml comment
* Fix unittests after refactoring patchengine.ApplyOperation(string,...) to patchengine.ApplyOperation(JsonNode,...)
* Refactor base classes
* Apply suggestions from code review
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Optimizations and refactoring of the patcher/engine/parser
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Allows save of a relation type without a child and/or parent object type.
* Addressed code review feedback and code health warnings.
---------
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
* Updated ui helper for select content card
* Updated ui helper for select media card
* Added ui helper for clear selection button
* Added tests for bulk action in list view content
* Added more tests for clear selection button in list view media
* Make tests run in the pipeline
* Reverted npm command
* Batch thumbnail URL requests to avoid N+1 API calls.
* Handle code review feedback.
* Remove extra newlines.
* chore: formats code
* Use @consumeContext decorator and remove await #init from imaging repository.
Replaces the blocking `await this.#init` pattern with the `@consumeContext`
decorator so the store is consumed opportunistically. This removes the async
gap before batchImagingRequest calls, allowing all thumbnails mounting in the
same Lit render pass to be collected into a single batched API request.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Move imaging URL cache into the request batcher and deprecate UmbImagingStore.
The batcher now owns a module-level URL cache, eliminating the need for the
context-based UmbImagingStore. This removes all context-request events from
the imaging repository and thumbnail hot path. The repository delegates
entirely to the batcher for caching and fetching. UmbMediaDetailRepository
uses the new clearImagingCache() export directly instead of instantiating an
imaging repository. Items with no URL (non-image media) are cached as empty
strings to prevent unnecessary re-fetching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Remove extra newlines.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(elements): add contentTypeIcon observable and _handleSave override to workspace context
Adds contentTypeIcon observable, icon field to UmbElementDetailModel, and maps icon from server response. Adds _handleSave override to remap validation error colors to warning colors during save, matching Document workspace behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(elements): add loading state, variant selector, and cleanup to split view
Adds loading state observation and binding, variant selector slot with new element-specific variant selector component, and element sortVariants utility. Removes dead #breadcrumbs CSS rule and reorders splitViewIndex to match Document workspace conventions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(elements): wire up publishing workspace context in variant selector
Consumes UMB_ELEMENT_PUBLISHING_WORKSPACE_CONTEXT in the element variant selector, mirroring the Document pattern. Fixes PUBLISHED_PENDING_CHANGES localization to use the correct key.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(elements): add save modal for element workspace variant picker
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Adds "Update" permission condition on Folder Rename entity-action
* feat(elements): add pending changes manager for element workspace
Mirror the Document workspace's UmbDocumentPublishedPendingChangesManager
to provide client-side comparison of persisted vs published element data.
The variant selector now uses this manager to determine pending changes
state instead of relying solely on the API state. The actual API call to
fetch published element data is left as a TODO until the backend endpoint
exists.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update src/Umbraco.Web.UI.Client/src/packages/elements/modals/save-modal/element-save-modal.element.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/src/packages/elements/utils.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* refactor(menu): delegate breadcrumb href to menu structure context
Move the href resolution logic from the breadcrumb element into the
menu structure workspace context via a new `getItemHref` method on the
interface and base class. This eliminates the need for duplicate
breadcrumb elements that only differ in href behavior, and mirrors the
existing pattern used by the variant breadcrumb.
* feat(elements): add menu structure context and breadcrumb for element folders
Add UmbElementFolderMenuStructureContext that overrides getItemHref to
make folder ancestors and the section root clickable in the breadcrumb.
Register the menu structure context and breadcrumb footer app in the
element folder workspace manifests.
* fix(elements): provide synthetic variant data for folder tree items
Folders don't have variants from the API, so provide a synthetic
published variant using the folder name. This prevents errors when
the tree item mapper expects variant data.
* Updates "umb-element-table-collection-view"
to add the column elements for "name" and (published) "state".
* Refactor exports in constants.ts for clarity
* fix(workspace): prevent breadcrumb TypeError for contexts without getItemHref
Menu structure contexts that don't extend the tree base class (e.g.
UmbLanguageNavigationStructureWorkspaceContext) lack getItemHref, causing
a runtime TypeError in the breadcrumb element. Use optional chaining to
gracefully handle missing implementations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(menu): add JSDoc to UmbMenuStructureWorkspaceContext interface
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
* Fixes "files/folders/files or folders" selections for the various media picker components, re-allowing folder selection from a media picker.
* Import and use enim instead of hardcoded enum value
---------
Co-authored-by: kjac <kja@umbraco.dk>
* Show ancestor path in document search results.
* show ancestor breadcrumb path in media search results
* Show the document ancestors name by culture variant
* Extract ancestor fetching to reduce cyclomatic complexity
* Add early return inside #fetchAncestors
* Handle errors from the api call.
* Add fallback title when the name doesn't exist
* Use full item models for search ancestor types
* Batch delete in DocumentUrlRepository and DocumentUrlAliasRepository to avoid exceeding SQL Server's 2100 parameter limit.
* Address code review feedback.
* Remove the unnecessary trigger rebuild on startup statement in the SQL Server migration path.
* Adds "umb-element-tree-item" custom component
Updates context to use the item data resolver..
* Adds manifests for Element entity-signs
for "Has Pending Changes" and "Has Scheduled Publish"
* Update src/Umbraco.Web.UI.Client/src/packages/elements/tree/element-tree-item.element.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Attempt to fix the Item Data Resolver `setData` type-casting
* Align element tree item model with item model for type safety
Add required `flags` field to `UmbElementTreeItemModel` (via
`UmbEntityWithFlags`) and `UmbElementTreeItemVariantModel`, matching
the document tree pattern. This ensures the data resolver's `#setFlags()`
receives actual data instead of silently accessing undefined properties.
The `as unknown as` cast in the context remains due to nominal type
differences (entityType union, variant state enum) but is now structurally
safe at runtime.
* Maps `flags` in `UmbElementTreeItemVariantModel`
* Updated locator for element tree item due to UI changes
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
Co-authored-by: Nhu Dinh <hnd@umbraco.dk>
* Compute next delay to compensate for time drift
* Addressed case flagged on code review following stopped service.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Added instructions for maintaining the `OpenApi.json` file
* Updated client-side instruction docs
for clean code and style guide.
* Updated "Full API surface" point
* Update CLAUDE.md
Co-authored-by: Andy Butland <abutland73@gmail.com>
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Handle invalid redirect routes without slash in GetUrlFromRoute
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Handle fragment-only routes before parsing node id
* Add unit tests verifying the fix (as well as expanding the test coverage of the URL provider in general).
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* feat: surface ProblemDetails detail in error notifications
Pass the ProblemDetails detail field through to error notifications.
Short details (≤250 chars) are shown inline with CSS line-clamp.
Long details (>250 chars) are shown via a "See error" button that
opens the error viewer modal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address PR review — rename detail/details ambiguity and remove as any cast
Rename local `details` variable to `errors` to avoid confusion with `detail`.
Change UmbErrorViewerModalData to a union type (UmbPeekErrorArgs | string)
matching what the modal actually handles at runtime, eliminating the as any cast.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: tighten types and overload _peekError with UmbPeekErrorArgs
- Document UmbPeekErrorArgs interface and its properties
- Add `errors` property to UmbPeekErrorArgs, deprecate `details`
- New _peekError overload: accepts UmbPeekErrorArgs directly
- Old _peekError overload: positional args, deprecated for removal in v19
- Update notification element and interceptor to use `errors`
- Widen UmbErrorViewerModalData to also accept Record<string, unknown>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: extract duplicate errors fallback to #validationErrors getter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove unnecessary null handling in interceptor #peekError
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve tsc errors from type tightening
- UmbErrorViewerModalData: use Record<string, unknown> interface to
satisfy UmbModalToken's object constraint (string not allowed)
- Cast detail string through unknown when opening error viewer
(modal handles strings at runtime, token type doesn't allow it)
- Fix interceptor errors Record to use string[] values
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve eslint errors — unused import, prettier, jsdoc link
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: renames 'See error' button to 'Full Error Message'
* feat: renames Danish button 'Undtagelsesdetaljer' to 'Fejldetaljer'
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add PublishedCultures and UnpublishedCultures to ElementCacheRefresher.JsonPayload
Adds culture-specific publishing details to the element cache refresher payload,
matching the existing ContentCacheRefresher.JsonPayload structure. Also replicates
the performance optimization from #21415 by only clearing partial view cache when
there are actual publish/unpublish culture changes, and fixes the Remove change
type check to use HasType instead of equality (flags enum).
* Reuse content cache logic for partial view cache clearing
---------
Co-authored-by: kjac <kja@umbraco.dk>
* Add workspaces docs, CLAUDE link, and skill
* Export workspace elements as element
* consolidate information
* adjust skill to make use of generic name component
* try to force the agent to follow docs and use skills
* Update SKILL.md
* clean up create package skill
* use data type package as reference
* add initial repository doc + skill
* Update src/Umbraco.Web.UI.Client/docs/workspaces.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/docs/workspaces.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update workspaces.md
* clean up
* Update SKILL.md
* Delete Repositories.md
* Create repositories.md
* Update repositories.md
* Normalize repositories doc links to lowercase
* Update src/Umbraco.Web.UI.Client/.claude/skills/general-create-repository/SKILL.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix data flow link path casing
* fix casing
* export as api + inline store in manifest
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Prevent Host header poisoning of ApplicationMainUrl.
* Introduce options for Umbraco application URL detection and handle situations where it can be undefined.
* Prevent email operations if the application URL is not detected or configured.
Improve log warnings.
* Addressed feedback from code review.
* Move startup application URL logging to a handler.
* Clean up ambiguous log message
---------
Co-authored-by: kjac <kja@umbraco.dk>
* Uncommented placeholders for restore endpoints
* Delete (inside Recycle Bin): wired up correct endpoints
* Added condition for "Empty Recycle Bin" collection-action
to only display in the Recycle Bin root.
* feat(recycle-bin): add destination entity overrides to restoreFromRecycleBin kind
Add optional destinationItemRepositoryAlias, destinationItemDataResolver,
and destinationRootEntityType properties to support cross-entity-type
restore (e.g. element restoring into element-folder). Existing document
and media manifests are unaffected as all new properties fall back to
the original values. Also adds element folder restore manifest.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(recycle-bin): extract #resolveDestinationItemName to reduce complexity
Extract resolver logic from setDestination into a dedicated method to
bring cyclomatic complexity under the threshold of 9.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Removed Restore Element Folder From Recycle Bin Entity Action
(This is for a separate PR)
* feat(elements): enable element and folder restore from recycle bin
Uncomment element restore manifest with destination overrides, add
folder picker modal, and add null guard for restore item lookup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fixes bug with selecting the Root for the restore target
* Corrected manifest aliases to use appropriate entity-type name for `ElementFolder`
* Added `UmbElementFolderItemDataResolver` to resolve folder names in recycle bin restore modal
* E2E: QA Added acceptance tests for restoring elements and deleting elements from recycle bin (#22069)
* Updated test helper for move a folder to recycle bin
* Added tests for restore element and delete element from recycle bin
* Added ocmment for the failing tests
* Make recycle bin tests run in the pipeline
* Fixed comment
* Removed duplication code
* Reverted npm command
* Adds `itemDataResolver` to the Element Trash entity-action
* Makes trashed Element Folder name to be read-only
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
Co-authored-by: Nhu Dinh <150406148+nhudinh0309@users.noreply.github.com>
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* add info workspace view into document blueprint
* Add history panel
* update document type route
* remove comment
* move time options format to ultils
* add blueprint auditlog model
* save move action and add authorization for audit log request
* add default implement
* update open api json
* Reused the `workspaceInfoApp: auditLog` kind
Added the manifest for the repository.
Removed the duplicated/unused code.
* UI tweaks + linting
* Renamed "Document Blueprint Workspace View Info Element" file/tag
* Restored the "UmbDocumentBlueprintAuditLog" types
* Add JSDoc to document blueprint audit log repository
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Export audit-log module from document-blueprints index
Adds the missing re-export so UMB_DOCUMENT_BLUEPRINT_AUDIT_LOG_REPOSITORY_ALIAS
is reachable from @umbraco-cms/backoffice/document-blueprint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
Co-authored-by: leekelleher <leekelleher@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
* claude review md files
* rename to review
* auto-detect target-branch via GH CLI
* Verify GH CLI is Available
* update table to fit github markdown format
* condensed the output to the essense
* State if the PR is too bad
* using the word `and´
* only relevant suggestions
* clean up
* narrow the scope for large PRs
* diff-first approach with selective reads
* specify that the header_only are amount of file where the only extra loaded is the header
* Complexity detection
* Classification of the PR
* improve other changes
* Ensure Types are kept intact in their type Hierarchy
* align test naming with project, and clean up instructions
* remove hardcoded Claude.md file table for a pattern
* improve skill description
* improved breaking change detection for front-end
* do not suggest breaking changes for PRs targeting main
* rename skill to umb-review
* less nit picky
* first version of skill evals
* Update .claude/skills/umb-review/references/coding-preferences.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update .claude/skills/umb-review/references/impact-analysis.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* remove mentioning the skill action it self
* split out GH CLI guideline
* improve file loading strategy
* make feedback extremely concise
* improve skipped files output
* latests eval
* added further evals
* move summaries into references
* separate Complexity Assessment into a reference file
* Complexity Assessment: secure mixed is still check despite other rules it out
* dont include gen.ts files
* iter 9 evals
* latests eval of 4
* keep only one test for complexity-advisory
* adjusted skill and Evals to match expectations
* improve sibling lookups
* improve skill regarding nit picks and C# patterns
* remove insecure manifest check
* final eval run
* eval grading
* remove review workspace
* remove umb review workspace part 2
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add workspaces docs, CLAUDE link, and skill
* Export workspace elements as element
* consolidate information
* adjust skill to make use of generic name component
* try to force the agent to follow docs and use skills
* Update SKILL.md
* clean up create package skill
* use data type package as reference
* Update src/Umbraco.Web.UI.Client/docs/workspaces.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/docs/workspaces.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update workspaces.md
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Present only changed variants as selected by default when saving and publishing.
* Detect pending changes on document load to ensure language selector variant status reports correctly.
* Avoid concurrent loads.
* Fix issue where with two variants changed but only one saved, both would display with pending changes.
* Addressed code review feedback.
---------
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
* Element Picker property-editor: adds "Start Node" configuration
* [WIP] Adds server config for Element start node
* [WIP] Attempts to wire up the `dataTypeId`
for the Element Picker start node
* Removed `StartNodeId` from the server config
* Implemented `requestTreeStartNode`
on Element Picker data-source
* Fix duplicate config entries in input-element property setters
The `folderOnly` and `startNode` setters used `.push()` without
deduplication, causing config entries to accumulate on Lit re-renders.
Filter existing entries before pushing to prevent duplicates.
* Update OpenAPI spec and regenerate TypeScript bindings
Add dataTypeId query parameter to element tree endpoints.
* Refactor input-element to compute dataSourceConfig on demand
Replace mutable #dataSourceConfig array with plain Lit properties for
folderOnly and startNode, computing the config inline in render. This
eliminates the duplicate-entry bug and simplifies the component.
Also fix "dont" typo in ignoreUserStartNodes description.
---------
Co-authored-by: Nhu Dinh <150406148+nhudinh0309@users.noreply.github.com>
* Resolve and persist element start node IDs when updating a user
The UpdateAsync method in UserService only resolved Document and Media
start node keys to IDs, completely ignoring ElementStartNodeKeys from
the update model. This caused element start node configuration to be
silently lost on user save.
* Add ElementStartNodeNotFound status and fix XML doc for MapUserUpdate
Introduces a dedicated ElementStartNodeNotFound operation status to
distinguish missing element start nodes from missing element items in
other operations, consistent with ContentStartNodeNotFound and
MediaStartNodeNotFound. Also adds the missing XML doc param for
startElementIds on MapUserUpdate.
* Add blank line to re-trigger the build.
---------
Co-authored-by: kjac <kja@umbraco.dk>
* TipTap: Add width/height to edit image properties (AB#65981)
Add width and height input fields with aspect-ratio lock toggle to the
media caption/alt-text modal. Thread dimensions through the toolbar
action so existing image dimensions are preserved when editing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* TipTap: Add double-click to open edit modals for images and embeds
Move double-click detection into node extensions via addProseMirrorPlugins
(tiptap-native). Extensions dispatch a generic DOM event, input-tiptap
delegates to the toolbar, and the toolbar executes the active action.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* TipTap: Improve edit image properties, unify embed dimensions, fix figcaption bug (AB#65981)
- Add width/height fields with aspect-ratio lock and maxImageSize cap to image modal
- Unify embed modal dimensions UI with image modal (inline row, lock button, px postfix)
- Fix figcaption cursor bug: editing from inside caption no longer opens new image picker
- Pass user dimensions to imaging endpoint for valid HMAC-signed URLs
- Preview image updates aspect-ratio when dimensions change
- Slim down toolbar API: inline pass-through methods, remove dead code
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add missing width: 100% to image modal dimension inputs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use display:block instead of width:100% on dimension inputs
Prevents the right border of the px affix from being clipped.
Applied to both image and embed modals for consistency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove explicit sizing on dimension inputs, let flex handle it
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use @input instead of @change on embed dimension fields
Aligns with image modal behavior so constrained dimensions update
on keystroke. Preview fetch is debounced at 500ms to avoid spam.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address Copilot review feedback
- Wrap imageSize() in try/catch so modal remains usable on broken URLs
- Recalculate aspect ratio on re-lock in image modal (matches embed)
- Change min="0" to min="1" on dimension inputs (both modals)
- Fix constrain truthiness check to use !== undefined
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* TipTap: Use maxImageSize config for embed defaults, update ratio to 16:9
Replaces hard-coded 360x240 (3:2) embed defaults with maxImageSize from
RTE config and a 16:9 aspect ratio matching modern video embeds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: select figure before replacing when editing from figcaption
When cursor was inside a figcaption, insertContent would insert a new
figure at the cursor instead of replacing the parent figure. Now selects
the figure node via setNodeSelection before proceeding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: export UMB_TIPTAP_NODE_DBLCLICK_EVENT from tiptap constants
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: removes double-click handling (to be implemented later on)
* Apply suggestion from @AndyButland
Co-authored-by: Andy Butland <abutland73@gmail.com>
* feat: adds constants for default width and height and guards against 0-values
* feat: validates that width and height are larger than 1px
* refactor: Extract shared <umb-input-dimensions> component
Deduplicates the width/height dimension input logic that was repeated
in both the media caption/alt-text modal and the embedded media modal.
The new component supports aspect ratio locking, proportional resize,
disabled state, and an optional reset-to-natural-dimensions button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: embeds should be constrained by default
* feat: defaults embed constrain to true
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: always fetch natural dimensions so reset button appears when editing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: move reset button below dimensions and cap natural size to maxImageSize
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: cleanup
* fix: use general_clear localization key for reset button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: constrain embed preview to sidebar width using aspect-ratio
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: target any first-child element in embed preview, not just iframe
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: add comment explaining generic selector for oEmbed markup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use height auto to let embed scale naturally from width
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use !important on width to override inline oEmbed attributes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use height 100% so iframe fills the aspect-ratio container
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: smooth embed preview aspect-ratio changes with CSS transition
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: smooth image preview aspect-ratio changes with CSS transition
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: show Clear button on embed dimensions using default size as natural
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: use maxImageSize for embed natural dimensions and Clear button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: media-with-caption modal should be 'medium'
* feat: address review feedback on dimensions and preview
- Rename reset button label from general_clear to general_reset (new key)
- Fix embed preview: use pixel width + aspect-ratio + max-width for
accurate proportional preview at any dimension
- Apply same width+aspect-ratio approach to image preview
- Add uui-box to media caption modal for consistent sidebar background
- Center image and embed previews in their containers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: simplify embed modal — honest dimensions, responsive iframe preview
Remove maxImageSize and naturalWidth/naturalHeight from embed modal since
oEmbed dimensions are hints (maxwidth/maxheight), not guarantees. Add
localized description explaining this to the user. Fix iframe preview
collapsing to 150px by reading width/height attributes and applying
aspect-ratio via JS (iframes lack intrinsic dimensions unlike images).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: recalculate aspect ratio when dimensions are set externally
When width/height properties are set from outside (e.g. after async
imageSize() resolves), the ratio was not recalculated — leaving it
undefined from connectedCallback. This caused locked mode to silently
fail on first appearance of the media caption/alt-text modal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
Remove unused recycleBin keys from XML language files
The recycleBin area contained keys (contentTrashed, mediaTrashed,
elementTrashed, elementContainerTrashed, itemCannotBeRestored,
itemCannotBeRestoredHelpText, wasRestored) that are no longer
referenced by any backend code since the audit logging was removed
from RelateOnTrashNotificationHandler in #21481.
* RichTextEditor: Filter media picker to allowed media types (closes#21824)
Add allowedMediaTypes config to the RTE data type, filtering the media
picker tree to only show selectable media types. Also applies type-aware
validation to drag-and-drop uploads using UmbMediaTypeStructureRepository,
with a modal picker when multiple types match a dropped file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Review fixes: cache media type lookups, remove unnecessary localization keys, fix lint
- Cache requestMediaTypesOf results per extension to avoid redundant API calls
when dropping multiple files with the same extension
- Add try/catch around API call to prevent unhandled rejections from crashing
the upload loop
- Remove custom localization keys, reuse same plain strings as MNTP config
- Fix prettier formatting warnings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Auto-Pick in media type picker modal no longer silently fails
The modal returns `{ mediaTypeUnique: undefined }` for auto-pick, which
was treated as a cancellation. Now distinguished from cancel (rejected
promise) and falls back to the server's preferred type.
Fixed in both the media dropzone manager and TipTap drag-drop upload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: Add localization keys for allowedMediaTypes config, reorder weight
Move allowedMediaTypes next to mediaParentId (weight 91) as they are
related media config options. Use #rte_config_* localization pattern
matching other RTE config properties.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Show notification when pasting disallowed file types into RTE
The MIME-type pre-filter silently dropped non-image files on paste
(and drag-drop). Now shows the same disallowed file type notification
as the media type validation path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: Add server-side validation for RTE AllowedMediaTypes config
Validates that media items referenced via data-udi in RTE markup are of
an allowed media type. Follows the same pattern as MNTP's
AllowedTypeValidator. Includes unit tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Clean up validator tests: remove unused param and region markers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Use splitStringToArray for config parsing consistency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Include media name in validation error for disallowed media types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: Fix and add acceptance tests for RTE allowedMediaTypes config
* feat: Default RTE to Image and SVG allowed media types
Set allowedMediaTypes to Image and Vector Graphics (SVG) in the
default Rich Text Editor data type seed for new installs. Also
update the Vite mock data to match.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Address Copilot review feedback
Fix test helper that swallowed null allowedMediaTypes parameter,
masking the "no filter configured" test case.
Remove redundant upload failure toast that showed a misleading
"disallowed media type" message for non-validation failures
(the upload manager already handles its own error notifications).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Use constants for seed GUIDs, normalize file extension casing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Refactored media type checks into helper shared across RTE and media picker.
Resolved case insensitivity edge case.
Removed unnecessary obsolete constructor.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Add flag support for pending changes and scheduled publish
Add entity sign manifests, tree item rendering, and flag provider
support so element tree items display pending changes (pencil) and
scheduled publish (clock) icons, mirroring the existing document
behavior.
Refactor flag providers and presentation factories to reduce
duplication, and move shared IHasFlags implementation into
PublishableVariantResponseModelBase.
* Fix HasScheduleFlagProvider test mocks to match refactored per-item lookups
* Extract PublishableVariantItemResponseModelBase to deduplicate variant item models
* Extract shared base class from Document/Element presentation factories
Introduce PublishableContentPresentationFactoryBase to eliminate code
duplication between DocumentPresentationFactory and ElementPresentationFactory.
Add async alternatives (CreateVariantsItemResponseModelsAsync,
CreateItemResponseModelAsync, PopulateFlagsAsync) and migrate callers in
async contexts to use them. Sync callers in tree/recycle bin controllers
use .GetAwaiter().GetResult() to avoid breaking changes in base classes.
Add IPublishableContentEntitySlim overload to DocumentVariantStateHelper
to unify the identical IDocumentEntitySlim/IElementEntitySlim overloads.
Make RelationTypePresentationFactory properly async with Task.WhenAll.
* Fix flags fallback to use empty array instead of empty string
* Acceptance Tests: Fix element tree item locator to match both elements and folders
The element tree renders umb-element-tree-item for elements but
umb-default-tree-item for folders. Update the E2E test helper locator
to use :is() to match both custom element types.
* Split HasScheduleFlagProvider into document and element providers
Address PR review feedback:
- Split HasScheduleFlagProvider into HasDocumentScheduleFlagProvider and
HasElementScheduleFlagProvider with a shared HasScheduleFlagProviderBase
- Fix N+1 query: use batch GetContentSchedulesByKeys instead of per-item
GetContentScheduleByContentId
- Add GetContentSchedulesByKeys to IPublishableContentService and implement
in PublishableContentServiceBase, removing the duplicate from IContentService
and ContentService
- Inject TimeProvider into base class, replacing DateTime.Now with
_timeProvider.GetUtcNow()
- Split tests to match new provider structure and verify batch retrieval
* Make tree and recycle bin mapping methods async
Remove .GetAwaiter().GetResult() calls introduced by the element flag
support changes. Rename MapTreeItemViewModel to MapTreeItemViewModelAsync
and MapRecycleBinViewModel to MapRecycleBinViewModelAsync across all
tree and recycle bin controllers, properly awaiting async factory calls.
* Extract Task.WhenAll select expressions into named variables
* Add missing XML docs to async methods on IDocumentPresentationFactory
* Fix DateTime vs DateTimeOffset comparison in schedule flag provider
Compare schedule.Date against _timeProvider.GetUtcNow().UtcDateTime
instead of the DateTimeOffset directly, avoiding implicit conversion
issues with DateTimeKind.Unspecified.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
* Fixed label in account menu button
The account menu button in the backoffice header was displaying user initials
visually (e.g., "AB") but the accessible name only showed "Profile options",
violating WCAG 2.5.3 which requires that when a UI component has visible text,
the accessible name must contain that visible text.
This fix ensures voice navigation software (e.g., Dragon NaturallySpeaking) can
properly recognize commands using the visible initials.
Changes:
- Added getInitials() utility function to extract first and last initial from user names
- Updated current-user-header-app component to include user name and initials in the
button's accessible label (aria-label)
- Updated profileOptions localization term in all 15 language files to include
placeholders for user name and initials using %0% and %1% format
Result:
- Visual display: "AB"
- Accessible label: "User profile for Andreas Lykke Borg (AB)"
The visible initials are now included in the accessible name, providing a
consistent experience for all users including those using assistive technologies.
Fixes#21942
* Update src/Umbraco.Web.UI.Client/src/packages/user/current-user/utils/get-initials.function.ts
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Added a fallback profile options label if name is null or empty
* Added test for get-initials function
* Added note about duplicate get-initials function
* Replicated the logic from the UUI avatar
* Add TODO to use utility exposed from UUI library for extracting the initials.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
Fixes#22291
In order to show the right validation message:
- the repository code always notifies the validation failure message
(or a default failure message if none is received)
- in the data-source code, tryExecute is called with the option
to disable the default notification
Return the original error instead of faking success
* Allow copying of system media types.
* feat: Improve error message for system media type alias change
Replace the generic "Operation not permitted" error with a specific
"Alias change not permitted" message that explains the constraint and
suggests using the duplicate operation instead.
Also adds an ordering comment in DeepCloneWithResetIdentities and
a test assertion verifying the copy's alias is mutable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* add frontend claude context for architecture, deprecation, package-development
* update with developer roles
* tighten up for llm consumption
* add information about localization
* add section about kinds
* include test priority
* add llm docs for core primitives and data flow
* add info about caching
* add skills
* organize in folders
* flat list of skills
* Update src/Umbraco.Web.UI.Client/docs/architecture.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/docs/package-development.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* update skill name
* format tech stack based on claude recommendations
* add context about entities
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add more granularity to ContentTypeChangeTypes and handle for structucal changes (pending non-structucal changes).
* Integration tests to validate the granular, structucal change types
* Implement "other" changes
* Make "other" changes less granular.
* Update tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentTypeEditingServiceTests.ChangeTypes.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Clean up
* Add test proving the sub-flags do not collide
* Support change detection for both structural and non-structural changes in one operation
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
Add missing notifications to element container and element editing services
Add ElementDeletingNotification and ElementTreeChangeNotification to
ElementContainerService for EmptyRecycleBin, Move, MoveToRecycleBin,
and Delete operations, aligning with ContentService notification patterns.
Add ElementTreeChangeNotification to ElementEditingService for Move
and Copy operations.
Refactor DeleteDescendantsLocked to return deleted elements and
DeleteItem to return the deleted entity for use in tree change
notifications.
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
chore(tests): remove dead KeepAlive config remnants
The KeepAlive feature was removed in b619399edb (#15891) but references
to the config remained in 8 acceptance test appsettings.json files and
2 CI pipeline env var definitions. These are no-ops since the setting
no longer exists — remove them.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Nhu Dinh <150406148+nhudinh0309@users.noreply.github.com>
* Update Microsoft.Extensions.Caching.Hybrid to latest minor, and other Microsoft dependencies to latest patch.
* Align test and local web project dependency versions.
* Remove obsolete code
* Update tests in BlockEditorBackwardsCompatibilityTests
* update languageId, remove obsolete construcor from ApiLink
* remove the tests
* Fixed build of unit tests.
* Reverted removal of UmbracoApiController for now (we should do this in a single PR).
* Code style fix.
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Added migration for SVG width/height
* #22114 worked on SVG width height implementation
* #22244 Code style fixes
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 XmlReaderSettings and using
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Cleanup
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Correction if statement
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Refactor log message
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Correction if statment
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Cleanup
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Cleanup
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Code style adjustments
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Adjust if statement
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Adjust documentation comments
Co-authored-by: Andy Butland <abutland73@gmail.com>
* #22244 Fix log comment
* #22244 Fallback to viewbox if width height attribute has other unit than numeric or px.
* #22244 Refactoring SVG parser, no support for decimals
* #22244 Migration, consistent logging
* #22244 Create vector umbracoWidth and umbracoHeight during clean install
* #22244 Remove SupportedImageType from ISvgDimensionsExtractor
* #22244 pass culture and segment to SetValue
* Add DtdProcessing.Prohibit security hardening to SvgDimensionExtractor.
* Addressed some code styling and robustness of the migration and extractor classes.
* Add further unit tests.
* Add logging to notification handler. Skip when properties don't exist to avoid unnecessary processing.
* Add unit tests for media saving handler.
* Move the dimensions extractor implementation into infrastructure.
---------
Co-authored-by: Markus Johansson <markus@obviuse.se>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* fix(core): append SiteName to machine identifier for same-host load balancing
When multiple Umbraco instances run on the same machine (e.g. IIS AAR load
balancing or local LB simulation), they shared the same machineId key in the
umbracoLastSynced table, causing cache sync interference. If Umbraco:CMS:Hosting:SiteName
is configured, it is now appended to the machine name to produce a unique
identifier per instance.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update tests/Umbraco.Tests.UnitTests/Umbraco.Core/Factories/MachineInfoFactoryTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Validate length
* Refactor to enable us to have a validator
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Added api helper for block grid area
* Updated ui helper for block grid area
* Updated tests for block grid area
* Updated json builder for blockGridSpecifiedAllowance
* Formatted code
* Updated ui helper for specifiedAllowance
* Updated tests
* Fixed ui helper for enterSpecifiedAllowanceMinByIndex
* Added ui helper for create content with a block area with specified allowance
* Added tests for create content with ablock grid area with specified allowance
* Format code
* Make tests run in the pipeline
* Fixed tests
* Fixed comments
* Reverted npm command
* Extend and tidy up unit and integration test coverage.
* Add MaxVersionsToDeletePerRun configuration setting.
* Added overload to GetDocumentVersionsEligibleForCleanup to allow restricting results to older than a given date and with a maximum count.
* Use SQL date filter and per-run cap in content version cleanup.
* Handle deletes using optimised process using temp tables.
* Make maxCount nullable and add per-run cap integration test.
* Addressed code review feedback.
* Fix to reporting of cap reached.
* Additional unit tests for max date cut-off logic.
* Add TODOs for removal of default implementations from interfaces.
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
* Revert timing for ContentVersionCleanupJob.
* Add index to versionDate on umbracoContentVersion.
* Ensure long command timeout for upgrade.
---------
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
Close readline before starting dev server
Close the readline interface before launching the Vite dev server so Ctrl+C can properly terminate the process.
* Added more constant variable for validation message
* Added api helper for creating multi url picker data type with min number
* Renamed
* Updated api helper for creating document with multi url picker
* Added tests for mandatory multi url picker
* Split out tests for content with a multi URL picker.
* Refactor and added tests for publish a block with empty mandatory multi url picker
* Make tests run in the pipeline
* Fixed comments
* Update MFA label to 2FA in English language file
* Changed MFA to 2FA in all other language files.
* Revert "Changed MFA to 2FA in all other language files."
This reverts commit 203294e287.
* Changed MFA to 2FA in all other language files.
---------
Co-authored-by: Marc Love <marc@madebycrunch.com>
* Handle API and surface controllers with correct status code and behaviour when a member isn't logged in.
* Addressed code review feedback.
* Further code review feedback.
* utilize the member type structure repo to get member create options
* align member collection create action with other content types
* remove hardcoded icon
* Update constants.ts
* register as create options
* restore label
* Remove ellipsis from document blueprint label
* Add collection create actions for tree item children
* Show ellipsis for labels with additional options
* Enable additional options for create actions
* Refactor language and member group create actions into create option actions
* Update UiBaseLocators.ts
* Add additionalOptions to create manifests
* Add ellipsis to names in create content modals
* Update DataTypeUiHelper.ts
* Update DocumentTypeUiHelper.ts
* Update creation action locators and tests
* Update LanguageUiHelper.ts
* Adds optional `requestStartNode`
to Entity Data Picker tree source confguration
* Changes the example Document data-source
to use a Document Picker for the start node,
instead of the Content Picker source.
As that is targeted across Documents, Media or Members.
* Example Documents data-source: implemented "start node"
* Renamed `requestStartNode` to `requestTreeStartNode`
* Code tidy-up
* Fix issue where dynamic node query based from current node does not resolve for new documents.
* Add tests verifying the fix. General cleanup of code warnings in dynamic node implementations and tests.
* Addressed failing integration test and code review feedback.
* Allow saving document blueprints with partial variant names.
* Address code review feedback.
* Use shallow copies instead of in-place mutation when filtering unnamed variants before delegating to base class validation.
---------
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
* preserve connectionString befor disposing EfCoreDatabase during dispose of EfCoreScope. Fixed by Claude Sonnet 4.6
* Add details of integration tests to memory files.
* Ensure original connection string is captured and remove unnecessary guard.
* Add further test verifying the fixed behaviour.
* Test clean-up.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Updated helpers
* Moved to specific test files
* Added tests with compositions
* Updated helper
* Run tests on pipeline
* Fixed
* Updated helpers
* Added tests for variants
* Added tests
* Updated smoke
* Fixed
* Cleaned up
* Moved to before each
* Reverted test command
* Added ui helper for copy button
* Updated tests since the duplicate button is replaced by the copy button
* Update tests/Umbraco.Tests.AcceptanceTest/lib/helpers/UiBaseLocators.ts
Co-authored-by: Andreas Zerbst <73799582+andr317c@users.noreply.github.com>
---------
Co-authored-by: Andreas Zerbst <73799582+andr317c@users.noreply.github.com>
* Added constant variables for public access notification message
* Added ui helper for public access
* Added api helper for setup and delete public access
* Added api helper for create default member group
* Updated tests to use createDefaultMemberGroup instead of the directly create api
* Added tests for setting public access on content
* Added api helper for verify public access
* Updated ui helper for verify public access
* Updated tests for public access
* Make tests run in the pipeline
* Fixed comment
* Reverted npm command
* Added constant variable for healthCheckMessage
* Added appsetting file for imaging setting config tests
* Updates name
* Added project for imagingSettingConfig
* Added ui helper for verify health check of Imaging HMAC Secret Key
* Updated tests for HMAC secret key health check with default settings
* Added tests for HMAC secret key health check is not configured
* Makes test run in the pipeline
* Fixed comment
* Clean code
* Reverted npm command
* Clear stale connection on pooled DbContext before returning to pool.
* style: apply linter comment punctuation fix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Removed unnessary test.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Update Nunit and AutoFixture.Nunit to new versions
* Adding NonParallelizable
* Add blame-hang timeout to integration tests to detect hanging tests
* remove NonParallelizable, update NUnit3TestAdapter, add Ingore to CoreConfigurationHttpTests
* Resolve CoreConfigurationHttpTests hang with NUnit 4.
- Use Task.Run in CreateHost to escape NUnit 4's SynchronizationContext
which deadlocks sync-over-async calls from async test methods.
- Use await using for factory disposal to avoid same deadlock on shutdown
- Remove WithWebHostBuilder which wraps the factory in a
DelegatedWebApplicationFactory that bypasses the CreateHost override.
- Add ContentRoot property to UmbracoWebApplicationFactory so content
root can be set without WithWebHostBuilder.
- Set ModelsBuilder mode to Nothing to prevent BootFailedException.
- Add AddTestServices for infrastructure test doubles (MainDom, etc.).
* Revert changes to pipelines.
* Remove remaining CollectionAssert using legacy syntax.
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* init implementation
* Add template tree item-children collection and views
* add base class
* Use Settings section for document blueprint paths
* Inline customElement names and update typings
* Make table collection view buttons compact
* remove collection action again as they require create options to be registered first
* move file
* fix export
* fix const exports
* Extract template tree repository alias to constants
* Extract shared culture-resolution logic from ConvertBlockEditorPropertiesBase, ConvertLocalLinks, FixConvertLocalLinks, and MigrateSingleBlockList into PropertyDataCultureResolver, fixing a bug where NULL languageId (legitimate invariant data) was incorrectly treated as a deleted language reference.
Add unit tests covering all resolution paths including the bug scenario.
* Remove obsoletion on helper.
* Address code review feedback.
* Handle SetValue variation mismatch for invariant data on culture-varying compositions
* Fixed build error in tests.
---------
Co-authored-by: Sven Geusens <sge@umbraco.dk>
* Add to backoffice hosts
Add to backoffice hosts, rather than completely replacing the array
* Add unit tests verifying fix.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Adding a file system approach to subscriber servers
* Adding tests
* Alternative lazy injection
* Adding delegate unit tests and making classes internal sealed.
* Adding a check to see if database is readonly
* Modifying DatabaseReadOnlyAccessor.cs
* Add table view to media picker modal
* Use unique id in media picker selection handlers
* Add dateTime formatter and use in media picker
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Add dateTime localization tests
* localize view labels
* Persist media picker view in interaction memory
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Routing: Resolve URL segment collision for siblings differing only in punctuation (closes#22070)
When sibling documents have names that differ only in punctuation
(e.g. "Title" vs "Title."), the URL segment provider strips punctuation
and produces identical segments, causing routing conflicts.
Add collision detection in DocumentUrlService.CreateOrUpdateUrlSegmentsAsync
that checks sibling segments (from both the in-memory cache and the current
batch) and appends a numeric suffix (-2, -3, etc.) when a collision is found.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Routing: Move URL segment collision detection to DocumentRepository name uniqueness (closes#22070)
Reverts the DocumentUrlService approach (URL-level `-2` suffixes) in favour of
detecting collisions at the document name level. When two sibling names produce
the same URL segment (e.g. "Title" and "Title." both clean to "title"), the
existing `(1)` naming convention is applied to the name itself, which then
yields a distinct URL segment.
Changes:
- Revert DocumentUrlService collision resolution logic
- Override EnsureUniqueNodeName in DocumentRepository to augment sibling names
with phantom entries for URL segment collisions (via IShortStringHelper)
- Apply same augmentation in EnsureVariantNamesAreUnique for variant content
- Add IShortStringHelper constructor dependency (with obsolete compat pattern)
- Add unit tests verifying the phantom entry approach
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Routing: Refactor URL segment collision to direct segment comparison
Replace the indirect "phantom entries" approach with a clearer two-step
strategy as suggested in review:
1. Call base.EnsureUniqueNodeName() to handle literal name duplicates
2. Fetch siblings, compute URL segments, and increment (N) suffix until
the resulting segment is unique
This is easier to reason about and avoids manipulating the SimilarNodeName
algorithm. The trade-off is a second sibling fetch (same indexed query),
which only runs on save.
- Replace AugmentNamesForUrlSegmentCollisions with EnsureUniqueUrlSegment
- Apply same pattern in EnsureVariantNamesAreUnique
- Remove phantom entry unit tests from SimilarNodeNameTests
- Add integration tests on ContentService for both invariant and
culture-varying content with punctuation-only name differences
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Updated usages of obsolete constructors.
* Avoid second look-up of siblings data.
* Make EnsureUniqueUrlSegment unit testable, and add tests.
* Pass content.Id rather than 0 in variant unique name check.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* update outdated dependencies to their latest major versions
* change version of JsonPatch.Net back to 3.*.*
* Upgrade Umbraco.Code package
* Update tests
* Resolve NUnit 4 migration issues causing test hangs
* Fix for dotnet test on the pipeline.
* Debug: Fix attempt for integration tests on the pipeline.
* Revert pipeline changes and go back to 5.2.0.
* Debug: Omit suspect tests.
* Debug: Disable tests with timeout.
* Debug: Try 4.6.0.
* Debug: Added reference to Microsoft.CodeAnalysis.CSharp.Workspaces.
* Roll back NUnit upgrade.
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Optimise redirect tracker by avoiding re-producing of descendant nodes and avoiding descendant traversal when there has been no change to the node's URL segment.
* Delete inadvertently added file
* Allow URL segment providers to ensure descendent traversal if needed.
* Pushed missing files.
* Refactors to reduce large method code smells.
Change setOneContent to setOneSettings for initialSettings
Line 661 calls setOneContent() with settings data instead of setOneSettings(). This pushes the settings element into the contentData array.
* remove obsolete constructor
* adjust RootDictionaryTreeController constructor to use non-obsolete constructor and remove obsolete base
* todo action v18
* remove ActivatorUtilitiesConstructor atribute that there's only one constructor
* remove obsolete class and method
* remove obsolete code in v18
* remove obsolete code from repositories
* remove obsolete for blocks
* remove obsolete code from services
* remove Icomponent
* remove incorrect IRequestSegmmentService
* remove obsolete properties
* undo change of blocklayoutitembase because of test failed
* bring back somes code due to pr 21999
* bring back some codes and update ContentRouteBuildertests
* remove obsolete code from domains, notification controller and some services
* remove obsolete constructor from ElementMapDefinition
---------
Co-authored-by: Lan Nguyen Thuy <lnt@umbraco.dk>
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
* Updated naming
* Updated path to test files
* created tests
* Reverted retries change
* Updated imports
* Added step
* updates based on comments and clean up
* Added vars
---------
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
* Added .skip tags for the failing tests due to an actual issue
* Change the way to verify the validation message
* Added .skip tags for failing tests due to the actual issues
* Adding code comments to Umbraco.Cms.Api.Management
* Update src/Umbraco.Cms.Api.Management/Controllers/MemberGroup/UpdateMemberGroupController.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Cms.Api.Management/Controllers/DocumentBlueprint/MoveDocumentBlueprintController.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Cms.Api.Management/Controllers/DataType/CopyDataTypeController.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Cms.Api.Management/Controllers/DocumentType/CopyDocumentTypeController.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Cms.Api.Management/Controllers/DataType/IsUsedDataTypeController.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fixing a missing closing brace on return docs.
* Fixing issue raised by copilot.
Issue was:
Inconsistent use of T: prefix in cref attribute. Other parameters in this PR use the interface name directly without the T: prefix (e.g., <see cref=\"IContentTypeService\"/>). Remove the T: prefix for consistency.
* Fix broken <returns> tags.
* Fixed incorrect descriptions.
* Added missing description.
* Fix positioning of comments.
* Fixed indentation.
* Use standard text for view model properties.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Andy Butland <abutland73@gmail.com>
Co-authored-by: Emma L Garland <1649855+emmagarland@users.noreply.github.com>
* Updated multiURLPickerSettings as there is a new setting for Culture-specific document links
* Updated tests for verify the default configuration of multi url picker data type
* Increased time for waiting the loader icon disappears to avoid the flaky tests
* Updated tests for reset manual URL using remove button due to locator changes
* Added ui helper for card collection view in content
* Updated tests to reflect that grid view is now the default instead of list view.
* Updated ui helper for public access saving button due to UI changes
* Removed unused code
* Fixed comments
* Removed unused test folder
* Updated auth to clear storage
---------
Co-authored-by: Andreas Zerbst <andr317c@live.dk>
* Basic implementaion
* Tests and schema validation
* Attemp refactor
* Fix json single parent bug
* Surface doctype schema validation to management api
* Improve block schema and make validation errors less verbose
* fix validation error cleanup
* Improved GUID handling | added schema for all propertyEditors
* Add ContentTypeInputSchema
* move contenttype schemas to be actual jsonschemas
* Fix block limit on blocklist and grid
* add datatype schema batch
* Refactoring blocks json schema generation and add to richtext
* Package version update and more tests!
* ConvertToJsonNode optimization
* async refactor
* Add editorUiAlias to x-umbraco-properties and make DataType ref route dynamic
* Removed JsonSchema.net due to possible license issues
* Use void editor in the noop schema test
* Cleanup leftovers from Schema validation removal
* Move batch logic into batchcontroller
* Update src/Umbraco.Infrastructure/PropertyEditors/BlockJsonSchemaHelper.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Update src/Umbraco.Cms.Api.Management/Services/ContentTypeJsonSchemaService.cs
Improve lookup on building propertymetadata
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Fixed build error.
---------
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk>
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Provide more descriptive management API responses for invariant with variant composition.
* Improved messaging and fixed integration tests.
* Fixed ordering of new ContentEditingOperationStatus values so existing values retain their integer equivalent.
* Suppress breaking changes in integration tests.
---------
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
* poc of minimizing unrelevant validation messages
* remove submit method from interface
* remove call to re-validate, as that is already trigger via `updated`--callback
* Split content type validation for create and update to allow saving elements no longer permitted in library
* Add integration test for element update after AllowedInLibrary toggle
Verify that ElementEditingService.UpdateAsync succeeds when the content
type's AllowedInLibrary flag is set to false after the element was
created, covering the split validation introduced for create vs update.
* Move content type validation into TryGetAndValidateContentType override
Eliminate redundant content type lookups in CreateAsync and UpdateAsync
by moving the IsElement/AllowedInLibrary check into the
TryGetAndValidateContentType override, which distinguishes create from
update by checking if the model is a ContentCreationModelBase.
* Use Assert.Multiple for element property assertions in update test
* Extract IsAllowedLibraryElement static method for readability
* Added tests for content with element picker
* Added tests for element with element picker
* Bumped version
* Renamed tests
* Make tests run in the pipeline
* Bumped version
* Fixed failing tests
* Moved goToBackOffice step to beforeEach
* Moved goToBackOffice to beforeEach
* Fixed comment
* Fixed afterEach() step
* Fixed import
* Fixed
* Reverted npm command
* feat(recycle-bin): add destination entity overrides to restoreFromRecycleBin kind
Add optional destinationItemRepositoryAlias, destinationItemDataResolver,
and destinationRootEntityType properties to support cross-entity-type
restore (e.g. element restoring into element-folder). Existing document
and media manifests are unaffected as all new properties fall back to
the original values. Also adds element folder restore manifest.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(recycle-bin): extract #resolveDestinationItemName to reduce complexity
Extract resolver logic from setDestination into a dedicated method to
bring cyclomatic complexity under the threshold of 9.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Removed Restore Element Folder From Recycle Bin Entity Action
(This is for a separate PR)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(media): allow focal point to be set to null in image cropper
- Updated UmbImageCropperPropertyEditorValue type to allow null for focalPoint
- Changed component state to use null as default instead of { left: 0.5, top: 0.5 }
- Replaced logical OR (||) with nullish coalescing (??) to preserve null values
- Updated reset function to set focalPoint to null
- Added null handling in all rendering and calculation logic
- Components now default to center (0.5, 0.5) for display when focalPoint is null
Fixes#21273
* refactor(media): extract logic from initializeCrop to reduce function size
- Extracted mask dimension calculation into #calculateMaskDimensions
- Extracted mask style application into #applyMaskStyles
- Extracted image scale calculation into #calculateImageScales
- Extracted image position calculation into separate methods:
- #calculateImagePositionWithCoordinates (for existing crops)
- #calculateImagePositionWithFocalPoint (for focal point positioning)
- Extracted image style application into #applyImageStyles
- Extracted zoom level update into #updateZoomLevel
Reduces #initializeCrop from 72 lines to 33 lines, meeting CI/CD threshold of 70 lines.
Related to #21273
* refactor(media): replace primitive parameters with interfaces to fix code quality warnings
- Created ViewportDimensions interface to group viewport width/height
- Created MaskDimensions interface to group mask dimensions and position
- Created ImageDimensions interface to group image dimensions and position
- Refactored all functions to use interface objects instead of multiple primitives
- Reduced #calculateImageDimensionsAndPosition from 5 args to 2
- Reduced #calculateImagePositionWithCoordinates from 5 args to 2
- Reduced #calculateImagePositionWithFocalPoint from 4 args to 1
Fixes primitive obsession (85.7% -> reduced) and excessive function arguments warnings.
Related to #21273
* fix(media): update modal value interface to allow null focal point
- Updated UmbImageCropperEditorModalValue interface to allow null for focalPoint
- Added explicit null handling when assigning focalPoint in onChange handler
Fixes TypeScript build error where null focalPoint was not assignable to non-nullable type.
Related to #21273
* Refactor image cropper focal-point handling
* Set defaultFocalPoint to null in test file.
* Default focalPoint to null and adjust checks.
---------
Co-authored-by: Francluob <francluob.dev@gmail.com>
Co-authored-by: Engiber Lozada <89547469+engijlr@users.noreply.github.com>
Co-authored-by: Emma L Garland <1649855+emmagarland@users.noreply.github.com>
Co-authored-by: engjlr <enl@umbraco.dk>
* Added tests for element reference tracking in info tab
* Removed tags
* Make all ElementReferenceTracking tests run in the pipeline
* Moved goToBackOffice step to beforeEach
* Updated import file
* Make tests run in the pipeline before merging
* Fixed npm command
* Revert npm command
* Make local and global elements behave the same (use the same implementation)
* Await async calls, don't fire-and-forget
* Fix the remaining unit tests
* Flush static fields on friendly published extensions before starting tests
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Add permission-based filtering to element tree endpoints
The element tree endpoints now filter results based on the current
user's browse permissions via a new IElementPermissionFilterService,
mirroring the existing document tree behavior.
Also extracts shared filtering logic from DocumentPermissionFilterService
into a PermissionFilterServiceBase to avoid duplication.
* Add unit tests for ElementPermissionFilterService
* Replace document-specific inheritdoc with neutral XML docs in PermissionFilterServiceBase
* Fix GetPermissionsAsync to use the provided objectTypes parameter instead of hardcoded Document type
---------
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
Set AllowedInLibrary on element content type in permission tests
The GetElementPermissionsCurrentUserControllerTests were failing because the
test setup created an element content type without setting AllowedInLibrary
to true. The ElementEditingService.TryGetAndValidateContentType method now
requires both IsElement and AllowedInLibrary to be true for element creation.
* Handle element saving and copying notifications in complex property editors
Extend ComplexPropertyEditorContentNotificationHandler to also handle
ElementSavingNotification and ElementCopyingNotification, ensuring that
block property key replacement (BlockList, BlockGrid, RichText) is
applied to elements the same way it is for content.
* Add integration tests for element copy with block editors
Test that block keys are regenerated and block structure is preserved
when copying elements with BlockList, BlockGrid, and RichText editors,
for both invariant and culture-variant content.
* Add scheduled publishing support for elements
Move PerformScheduledPublish from IContentService to the shared
IPublishableContentService<T> interface so both documents and elements
support scheduled publishing.
Filter ClearSchedule and HasContentForRelease/Expiration queries in
PublishableContentRepositoryBase by NodeObjectTypeId to prevent document
and element schedules from interfering with each other.
Update ScheduledPublishingJob to process both document and element
schedules, and add integration tests verifying cross-entity isolation.
* Simplify ScheduledPublishingJob.ExecuteAsync
Extract duplicated scheduled publishing logic into a generic helper
method and include the entity type in the log message.
* Add element version cleanup to the content version cleanup background job
The existing ContentVersionCleanupJob only cleaned up document versions.
Element versions were left to accumulate despite having the same cleanup
service infrastructure available. This extends the job to also clean up
element versions using the same configuration toggle and schedule.
* Use PascalCase for structured logging names.
* Fixed code warnings and duplicate line breaks.
* Cleaned up usings.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Add missing AuditType.Copy audit log for element copy operations
Make the abstract Copy method in ContentEditingServiceBase async and
accept a Guid userKey instead of int userId, allowing the element
copy implementation to use the audit service directly. Add the
missing _auditService.AddAsync(AuditType.Copy, ...) call in
ElementEditingService.CopyAsync to match the document equivalent
in ContentService.Copy.
* Fix copy audit log to record against the original element
The copy audit entry was being logged against the new copy's ID
instead of the original element's ID, inconsistent with how
documents handle copy audit logging.
* Add audit log retrieval endpoint for elements and wire up frontend
Add GET /{id:guid}/audit-log endpoint following the document audit
log pattern. Wire up the existing frontend data source to call the
new API, add element-specific localization strings, and remove the
unsupported sort audit type.
Fix GUID repository cache key prefix in PublishableContentRepositoryBase
The merge of the GUID cache key collision fix (9ea0520) applied
IContent-specific changes from DocumentRepository's nested class, but
in v18/dev this code lives in the generic base class. Two issues:
- EntityByGuidReadRepository.GetCacheKey used the "uRepo_" prefix
while GuidReadRepositoryCachePolicy looks up entries with "uRepoGuid_",
causing PopulateCacheByKey to insert under a key the policy never finds.
- PersistUpdatedItem cleared GetGuidKey<IContent> instead of
GetGuidKey<TEntity>, so ElementRepository would clear the wrong key.
* Add AllowedInLibrary flag to content types
Add a new boolean property AllowedInLibrary across all layers to
indicate whether a content type is allowed in the library. This is
only meaningful for element types (IsElement = true).
Changes span the core domain model, Management API request/response
models, persistence DTOs/mappers/factories, and a database migration
to add the column to the cmsContentType table.
* Enforce AllowedInLibrary in ElementEditingService.CreateAsync
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(api): add AllowedInLibrary filter to document type search endpoint
Add allowedInLibrary query parameter to GET /document-type/search,
following the same pattern as the existing isElement filter. The old
SearchAsync overload without the parameter is preserved as a default
interface method and marked obsolete (scheduled for removal in v19).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(api): regenerate OpenApi.json and backoffice client types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(api): make search query parameter nullable for document type search
Allow the document type search endpoint to be called without a text
query, enabling filter-only usage (e.g. filtering by isElement and
allowedInLibrary without requiring a search term).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(api): replace search allowedInLibrary filter with dedicated endpoint
Revert the search endpoint changes (IContentTypeSearchService, controller)
and instead add a dedicated GET /document-type/allowed-in-library endpoint
that follows the AllowedAtRoot pattern. This ensures IContentTypeFilter
support and a cleaner API separation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test(api): add integration tests for GetAllAllowedInLibraryAsync and AllowedInLibraryDocumentTypeController
Add service-level tests verifying correct filtering by IsElement + AllowedInLibrary, pagination, and IContentTypeFilter integration. Add controller-level authorization tests for the allowed-in-library endpoint.
* Map allowedInLibrary through content type data sources
Add allowedInLibrary to UmbContentTypeModel and map it consistently
across document, media, and member type data sources for scaffold, read,
create, and update operations.
* Add AllowedInLibrary support to test builders and set it in all element tests
ElementEditingService.CreateAsync checks contentType.AllowedInLibrary and
returns NotAllowed if false. All element test types were missing this flag,
causing test failures. Adds IWithAllowedInLibraryBuilder interface, extension
method, and sets AllowedInLibrary=true on all element type creation in tests.
* Also enforce IsElement check when creating elements in the library
* Set IsElement and AllowedInLibrary on ElementPublishingServiceTests content types
* Remove AllowedInLibrary from document type tree item response model
The AllowedInLibrary property is not relevant for tree items and is not
used by the frontend. This removes it from the tree item model, its
mapping in the tree controller, and regenerates the OpenAPI spec and
TypeScript client accordingly.
* Refactor element content type validation into base class override
Make TryGetAndValidateContentType protected virtual in
ContentEditingServiceBase and override it in ElementEditingService to
check IsElement and AllowedInLibrary. This guards both create and update
paths (previously only create was guarded) and eliminates duplicate
ContentTypeNotFound handling.
Enable the previously-ignored
Cannot_Create_Element_Based_On_NonElement_ContentType test and add a new
test for the AllowedInLibrary check.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add webhooks for elements
* Review: Removed unused payload type
* Use new object as empty payload
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Elements: Add DisableDeleteWhenReferenced support and fix delete notifications
- Add DisableDeleteWhenReferenced check to ElementContainerService delete operations
- Fire ElementDeletedNotification and EntityContainerDeletedNotification per item during descendant deletion
- Fix potential infinite loop when items are skipped due to being referenced
- Simplify EmptyRecycleBinAsync to use DeleteDescendantsLocked directly
- Use path descending ordering for consistent deletion order (children before parents)
- Add test for descendant delete notifications
* Elements: Fix EmptyRecycleBin pagination with DisableDeleteWhenReferenced
When DisableDeleteWhenReferenced is enabled and some items are skipped,
the standard skip/take pagination breaks. This change:
- Adds SqlLessThan/SqlGreaterThan SQL expression extensions for string
comparison in LINQ queries
- Uses path-based cursor pagination instead of skip/take
- Tracks protected paths to prevent deleting containers that have
referenced descendants
- Adds ElementRecycleBin to UmbracoObjectTypes enum
* Tests: Add DisableUnpublishWhenReferenced tests for elements
Verify that DisableUnpublishWhenReferenced works correctly for elements
(inherited from ContentPublishingServiceBase):
- Cannot unpublish an element that is being referenced
- Can unpublish an element that is doing the referencing
* Elements: Remove redundant Trashed filter from DeleteDescendantsLocked
The Trashed filter was redundant because:
- EmptyRecycleBinAsync only operates on items under the recycle bin root
- DeleteFromRecycleBinAsync requires containers to be trashed, and all
descendants are marked as trashed when moved to recycle bin
Removing the filter simplifies the query and handles edge cases better.
* Elements: Add proper ProblemDetails responses for publish/unpublish endpoints
Move ContentPublishingOperationStatusResult from DocumentControllerBase to
ContentControllerBase so it can be shared. Add ElementPublishingOperationStatusResult
to ElementControllerBase and update PublishElementController and
UnpublishElementController to return proper error responses instead of empty
BadRequest() when operations fail (e.g., when DisableUnpublishWhenReferenced is enabled).
* Refactor: Use abstract EntityName for content controller error messages
Replace hardcoded "document" terminology in shared ContentControllerBase
error messages with an abstract EntityName property, so each subclass
(document, element, media, member, etc.) provides context-appropriate
error messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix: Check DisableUnpublishWhenReferenced when moving elements to recycle bin
ElementEditingService.MoveToRecycleBinAsync was missing the reference
check that ContentEditingService already performs for documents. This
allowed referenced elements to be moved to the recycle bin even when
DisableUnpublishWhenReferenced was enabled.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Prevent moving container to recycle bin when descendants are referenced
Add server-side validation to ElementContainerService.MoveToRecycleBinAsync
that checks for referenced descendants when DisableUnpublishWhenReferenced
is enabled. Uses ITrackedReferencesService.GetPagedDescendantsInReferencesAsync
as an upfront check before any move processing begins.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fix element delete blocked by trash-tracking relation
ElementEditingService was missing the RelateParentOnDeleteAlias
override, so the "relate parent on delete" relation created when
trashing was not excluded from the reference check. This caused
"Cannot delete a referenced content item" when
DisableDeleteWhenReferenced was enabled, even for unreferenced
elements.
* improvement(elements): general UI updates, element picker rework, and constants tidy-up
* fix(elements): forward min/max messages through umb-input-element and minor cleanups
Add minMessage/maxMessage properties to UmbInputElementElement so validation
messages are properly forwarded to the inner umb-input-entity-data component.
Also fix JSDoc grammar, variable naming, and comment tidying.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(elements): sync value/selection and register inner form control in umb-input-element
Add getter/setter overrides for value and selection that keep them in sync
(matching umb-input-content pattern), and register the inner umb-input-entity-data
via addFormControlElement() in firstUpdated() so validation propagates correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(elements): use correct element ID in referenced-by mock handler
Change sentinel ID from 'all-property-editors-document-id' to 'simple-element-id'
to match the actual element mock fixture IDs in element.data.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test(elements): add unit test for umb-input-element
Add instantiation and conditional a11y audit tests following the
umb-input-document.test.ts pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(elements): add element workspace validation repository
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Global Elements: Address Copilot review feedback on validation PR
Fix JSDoc comments on validation repository/data-source to accurately
describe validation behavior instead of persistence. Use barrel import
for validation repository and remove leftover commented-out code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Global Elements: Remove redundant guard clauses in validation data source
Remove TypeScript-redundant checks in validateCreate to reduce
cyclomatic complexity below the CodeScene threshold of 9.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
* feat(elements): add element reference tracking repository
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fixed linting errors
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The OpenAPI definition and backoffice TypeScript client were out of
sync with recent Management API changes already on v18/dev. Regenerated
to bring them up to date.
* Begin implementation of repo base
* Move internal mapping - part 1
* Move internal mapping - part 2
* Move versioning, persistence, GUID sub repo and utilities to base
* Fix wrong assumption in cache tests
* Move content repo + recycle bin to base
* Move schedule to base
* Move common delete clauses to base
* Move DTO mapping to base
* Fix a few of the pending TODOs for elements
* Abstract OnUowRefreshedEntity away to concrete implementations
* Handle template editing in a less hardcoded way
* Restore DTO visibility for elements
* Update src/Umbraco.Core/Cache/CacheKeys.cs
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Update src/Umbraco.Infrastructure/Persistence/Repositories/Implement/PublishableContentRepositoryBase.cs
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Update src/Umbraco.Infrastructure/Persistence/Repositories/Implement/PublishableContentRepositoryBase.cs
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Update cache key (review comment)
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Elements: Add restore from recycle bin functionality
- Add RestoreAsync to IElementEditingService and ElementEditingService
- Add RestoreAsync to IElementContainerService and ElementContainerService
- Add RestoreElementRecycleBinController and RestoreElementFolderRecycleBinController API endpoints
- Add TryGetContainedObjectType to EntityContainer for graceful handling of non-container types
- Update EntityContainerRepository to return null instead of throwing for non-container entities
- Add comprehensive integration tests for element and container restore operations
* Refactor: Remove entity return from Move/Restore/MoveToRecycleBin methods
Simplify the return types of IElementEditingService and IElementContainerService
move operations to return only the operation status instead of the entity.
These operations don't meaningfully change entity data (just location/state),
and no consumers were using the returned entities. Callers can use GetAsync
if they need the updated entity afterward.
* Fix: Capture original path before move for restore relation cleanup
The MoveEventInfo.OriginalPath was incorrectly set to the element's path
after the move, causing DeleteOriginalParentRelationsOnRestore to fail
because the path no longer contained the recycle bin path prefix.
* Tiny little formatting
---------
Co-authored-by: kjac <kja@umbraco.dk>
* Elements: Add reference tracking and recycle bin query support
- Add Element reference tracking API endpoints (referenced-by, are-referenced, referenced-descendants)
- Add Element recycle bin original-parent and referenced-by endpoints
- Add ElementReferenceResponseModel and ElementContainerReferenceResponseModel
- Add IElementRecycleBinQueryService for querying original parents of trashed elements
- Add Element relation type constants for parent tracking on delete
- Add translation strings for Element recycle bin operations
- Refactor RelateOnTrashNotificationHandler to reduce code duplication using generic helper methods
- Add Element and ElementContainer support to RelateOnTrashNotificationHandler
* Elements: Register Element notification handlers for relation tracking
Add Element and EntityContainer notification handlers for:
- RelateOnTrashNotificationHandler (move to/from recycle bin)
- ContentRelationsUpdate (track element content relations)
* Elements: Remove ReferencedDescendantsElementController
Elements are leaf nodes in the folder structure and cannot have
descendants, making this endpoint unnecessary.
* Elements: Fix ElementPickerPropertyEditor reference extraction
The element picker stores element IDs as Guids, not as UDI strings.
Updated GetReferences to deserialize as Guid array and create UDIs
from the Guid values.
* Elements: Fix TrackedReferencesRepository to include Element published state
Add LEFT JOIN to ElementDto and use COALESCE to get the published state
from either DocumentDto or ElementDto, fixing the issue where Element
references returned published = null.
* Elements: Add ReferencedDescendantsElementFolderController
Add endpoint to get referenced descendants of an element folder.
Unlike elements (which are leaf nodes), folders can have descendants
that may be referenced elsewhere.
* Elements: Add integration tests for Element reference tracking
Add TrackedReferencesServiceElementTests covering:
- GetPagedRelationsForItemAsync for Elements
- GetPagedRelationsForRecycleBinAsync for Elements
- GetPagedKeysWithDependentReferencesAsync for Elements
- GetPagedDescendantsInReferencesAsync for Element containers
* Elements: Add management API controller permission tests for Element reference endpoints
- Add ReferencedByElementControllerTests for element referenced-by endpoint permissions
- Add AreReferencedElementControllerTests for element are-referenced endpoint permissions
- Add ReferencedDescendantsElementFolderControllerTests for folder descendants endpoint permissions
- Fix GetManagementApiUrl to respect [FromQuery(Name="...")] attribute for proper URL generation
* Elements: Split OriginalParentElementRecycleBinController into two controllers
Split the controller to follow the controller-per-operation pattern,
consistent with DeleteElementRecycleBinController and
DeleteElementFolderRecycleBinController.
- OriginalParentElementRecycleBinController: for elements
- OriginalParentElementFolderRecycleBinController: for folders
* Elements: Fix user fallback for audit logging in RelateOnTrashNotificationHandler
Update the handler to properly resolve user key for audit logging, using a switch expression
to handle different entity types. Also sets CreatorId on EntityContainer creation.
* Tests: Fix duplicate query parameter in ItemElementItemControllerTests
Remove the ClientRequest() override that was appending a duplicate id query
parameter to the URL. The base MethodSelector already includes the element key
which gets converted to the query parameter by GetManagementApiUrl, causing
the URL to become ?id=<guid>?id=<guid> and model binding to fail.
* Tests: Fix permission controller tests to use correct entity types
These tests were passing on the base branch only because the URL was being
constructed incorrectly (missing query parameters). After be399134f8 fixed
the GetManagementApiUrl helper to properly include FromQuery parameters,
the tests now correctly build URLs and revealed that they were using user
keys instead of the expected document/media/element node keys.
Updated tests to create the appropriate entity type (document, media, or
element) and pass its key to the permission endpoints.
* Tests: Update RelationTypeRepositoryTest for new element relation types
Update expected counts and fix hardcoded ID lookup after new element
reference tracking relation types were added to the system:
- umbElement (RelatedElement)
- relateParentElementContainerOnElementDelete
- relateParentElementContainerOnContainerDelete
Changes:
- Store created test relation type in field to use actual ID instead of
hardcoded ID 9 which shifted when built-in types were added
- Update GetAll expected count from 9 to 12 (9 built-in + 3 test data)
- Update Count query expected from 6 to 8 (aliases starting with "relate")
* Refactor: Rename methods in RelateOnTrashNotificationHandler for clarity
Rename methods and parameters to better describe their purpose:
- DeleteRelationsOnRestore → DeleteOriginalParentRelationsOnRestore
- CreateRelationsOnTrashAsync → CreateOriginalParentRelationOnTrashAsync
- relationTypeAlias → originalParentRelationTypeAlias
- relationTypeName → originalParentRelationTypeName
These names clarify that the methods handle "original parent" relations
used for restoring items from the recycle bin, not all relations.
* Tests: Fix ReferencedDescendantsElementFolderControllerTests expectations
- Use unique folder names to prevent conflicts between test runs
- Add assertion to verify folder creation succeeds
- Correct expected status codes for Editor and Writer to OK (not NotFound)
The NotFound responses were caused by folder creation failures due to
duplicate names, not actual permission restrictions.
* Tests: Add success assertions to Element controller test setup methods
Add Assert.IsTrue checks after service calls in test setup to ensure
test prerequisites are correctly established before running actual tests.
This prevents silent failures in setup from causing misleading test results.
Assertions added for:
- ElementContainerService.CreateAsync (9 tests)
- ElementEditingService.CreateAsync (19 tests)
- ElementEditingService.MoveToRecycleBinAsync (6 tests)
- ElementContainerService.MoveToRecycleBinAsync (3 tests)
* Elements: Fix MapReference to return un-enriched response when entity not found
Return the mapped response model instead of null when the matching entity
cannot be found for enrichment. This preserves basic reference information
even when variant data cannot be loaded, preventing valid references from
being silently dropped.
Also clean up ElementContainerReferenceResponseModel formatting.
* Fix: Guard GetSlimEntities against empty keys to prevent loading all entities
* Fix: Return ParentIsTrashed status when original parent is in recycle bin
* Breaking: Remove duplicate sync notification handler interfaces
Remove INotificationHandler<ContentMovedToRecycleBinNotification> and
INotificationHandler<MediaMovedToRecycleBinNotification> interfaces along
with their obsolete sync Handle methods. Only the async handlers should
be implemented.
* Tests: Simplify TrackedReferencesServiceElementTests
- Simplify assertions in Get_Descendants_In_References test
- Create Element3 after folder creation to avoid unnecessary update
* Revert: Remove changes to be moved to separate PRs
Revert EntityTypeContainerService.CreateAsync CreatorId change and
permission controller test changes - these should be addressed in
separate PRs.
* Revert: Remove GetMediaPermissionsCurrentUserControllerTests changes
This change should be addressed in a separate PR for v17.
* Refactor: Move recycle bin audit logging to services
Move audit logging for recycle bin operations from RelateOnTrashNotificationHandler
to the individual services (ContentService, MediaService, ElementEditingService,
ElementContainerService). This simplifies the notification handler and keeps audit
logging closer to the operations being performed.
- Simplify audit messages to "Moved to recycle bin from parent {parentId}"
- Add AuditMoveToRecycleBin helper methods to Content and Media services
- Add AuditMoveAsync helper methods to Element services
- Remove unused audit dependencies from RelateOnTrashNotificationHandler
- Add obsolete constructor bridge for backwards compatibility
* Refactor: Extract GetParentIdFromPath extension method
Add GetParentIdFromPath string extension to consolidate duplicate logic
for extracting parent ID from entity path strings. This replaces 5
instances of the same path parsing pattern across services and handlers.
- Add GetParentIdFromPath to StringExtensions.Parsing.cs
- Inline audit calls in ContentService, MediaService,
ElementEditingService, and ElementContainerService
- Update RelateOnTrashNotificationHandler to use the new extension
- Add unit tests for the new extension method
* Refactor: Make CreateOriginalParentRelationOnTrash synchronous
Remove unnecessary async from CreateOriginalParentRelationOnTrash since
the method contains no async operations. Update handlers to return
Task.CompletedTask directly.
* Elements: Implement validation for Element editing endpoints
Move ValidateCulturesAndPropertiesAsync and GetCulturesToValidate from
ContentEditingService to ContentEditingServiceBase, enabling reuse in
ElementEditingService.
- Implement ValidateCreateAsync and ValidateUpdateAsync in ElementEditingService
- Update Element API controllers to return validation results properly
- Update all inheriting services (Media, Member, Blueprint) with new params
* Elements: Add validation tests for ElementEditingService
- Add tests for ValidateUpdateAsync and ValidateCreateAsync
- Cover invariant, culture variant, and permission-based validation scenarios
* Fix bad merge
* Removed unused fields
* Removed old editor UI
---------
Co-authored-by: kjac <kja@umbraco.dk>
* CRUD + folders + API
* Fix infinite recursion
* Distributed cache handling for Elements
* Publishing for Elements (incl. refactor)
* Fix bad file name
* Added "foldersOnly" option to the siblings endpoint
* Update src/Umbraco.Core/Models/UmbracoObjectTypes.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* API for publishing elements
* Published element cache (WIP)
* Fix delete at repo level
* Fixing up a little tests
* Element picker property editor
* Added tests to prove published element status
* Move scheduled content keys to base abstraction
* Add request caching for published element creation (similar to published document creation)
* Apply conditional appcache access to elements as well
* Fix test build errors
* Fix merge from main
* Fix merge
* Add cache invalidation on update (like content and media)
* Move element (incl. tests)
* Element copying
* Add items endpoint incl. variation info at item level
* Make the Element tree items look like Document tree items (with variations)
* Rename all things ElementType to DocumentType
* Move ElementRepository to the right place
* Fix auditing after merge (changes from #19357)
* Fix dates after merge (changes from #19822)
* Fix NPoco querying after merge (changes from #20184)
* Fix various build errors after merge
* Move containers
* Add migration to create element tables
* Re-implement #21105 at base class level
* Fix merge
* Add element tree recycle bin + move element to/from recycle bin
* Controllers for move to recycle bin + recycle bin root
* Support element containers in recycle bin (no controllers)
* Handle error cases for element moves and add more tests
* Do not allow creation of IPublishedElement for trashed elements
* Amend recycle bin controller output and add children controller
* Regenerate OpenApi.json with Element APIs
* Housekeeping: Organize element container service tests
* Fix bad housekeeping
* Add missing siblings controller for recycle bin
* Add "delete from recycle bin" and "empty recycle bin" operations (including API)
* Updated OpenApi.json to reflect new endpoints
* Added `CreateDate` to `ElementTreeItemResponseModel`
Marked `ElementRecycleBinItemResponseModel.DocumentTypeReferenceResponseModel` as nullable.
* Re-generated OpenAPI.json
* Add configuration endpoint for Elements
* Explicitly unpublish published elements when restoring from recycle bin.
* Elements: Remove invalid templateId from ElementVersionDto index definitions (#21384)
* Persistence: Remove invalid templateId from ElementVersionDto index definitions
The ElementVersionDto had index definitions that referenced templateId in
their IncludeColumns, but the ElementVersion table only has id and published
columns. This caused SQL Server clean installs to fail with error 1911:
"Column name 'templateId' does not exist in the target table or view."
This was likely a copy-paste error from DocumentVersionDto which does have
a templateId column.
* Ignore Cannot_Create_Element_Based_On_NonElement_ContentType for the time being
---------
Co-authored-by: kjac <kja@umbraco.dk>
* Fix the ordering of items in the tree
* It's 2026 now...
* Fix missing project structure
* Amend empty recycle bin
* Elements: Fix element recycle bin node insertion on SQL Server (#21390)
Enable IDENTITY_INSERT before inserting the element recycle bin node with an explicit ID, then disable it afterward. This fixes the migration failing on SQL Server with "Cannot insert explicit value for identity column" error.
* Fix count trashed children
* Moved newly added entity service tests to an isolated, per-test DB class so they do not interfere with the existing per-fixture DB tests
* Elements: Element start node permissions (#21375)
* Add Element start node support for Users and UserGroups
- Add StartElementId to UserGroup and element start nodes to User
- Add UserStartNodeFolderTreeControllerBase for tree filtering with folder support
- Update ElementTreeControllerBase to use start node filtering
- Add ElementTreeItemResponseModel.NoAccess property for "no access" items
- Add UserExtensions methods for element start node calculation
- Update User/UserGroup API models and factories
- Add database migration for startElementId column
- Add SectionAccessForElementTree authorization policy
Note: Granular element permissions deferred for future implementation
* Add element root access for default user groups on fresh install
Set StartElementId = -1 for Administrators, Writers, Editors, and
Translators user groups in DatabaseDataCreator, giving them element
root access on fresh installations (matching their content/media access).
* Add multi-type support to UserStartNodeEntitiesService
Added overloads to RootUserAccessEntities, ChildUserAccessEntities, and
SiblingUserAccessEntities that accept multiple UmbracoObjectTypes. This
enables querying for Elements and ElementContainers in a single call
rather than requiring separate queries for each type.
Also added GetAll and GetPagedChildren overloads to IEntityService and
IEntityRepository to support querying multiple object types efficiently
with a single database query.
* Add integration tests for Element start nodes with mixed hierarchy
Added UserStartNodeEntitiesServiceElementTests with a mixed hierarchy
structure containing both containers and elements at each level:
- Level 1: Containers (C1-C5) and Elements (E1-E3)
- Level 2: Child containers (C1-C1 through C1-C10) and Elements (C1-E1, C1-E2)
- Level 3: Leaf elements (C1-C1-E1 through C1-C1-E5)
This tests scenarios where containers and elements are siblings, ensuring
the access filtering works correctly for mixed-type queries.
Also refactored Content and Media tests to use a shared base class
(UserStartNodeEntitiesServiceTestsBase) to reduce code duplication.
* Add Library section for Elements
- Rename Constants.Applications.Elements to Library
- Add SectionAccessLibrary authorization policy
- Add library mapping to SectionMapper
- Grant Library section access to Administrators, Writers, and Editors on fresh install
- Update TreeAccessElements to use Library section
* Add Element tree controller authorization tests
Add integration tests for RootElementTreeController and
ChildrenElementTreeController to verify section-based
authorization works correctly for the Element tree endpoints.
* Fix ReadOnlyUserGroup not passing startElementId to constructor
The obsolete 13-parameter constructor was passing `null` instead of
the actual `startElementId` value to the next constructor, causing
user groups to appear to have no element start node access.
Also update UserFactory.ToReadOnlyGroup to pass the Description
parameter to the ReadOnlyUserGroup constructor.
* Add Element controller authorization tests
Add authorization tests for Element CRUD, Folder, RecycleBin, and Item
controllers to verify user group access permissions.
Tests cover Admin, Editor, Writer, SensitiveData, Translator, and
Unauthorized user groups for each controller endpoint.
* Re-generated OpenApi.json
* Fix Element start node handling to use ElementContainer object type
- Update UserStartNodeFolderTreeControllerBase to query both folder and
item object types when filtering by user start nodes
- Fix UserGroupPresentationFactory to use ElementContainer instead of
Element when resolving element start node IDs/keys
* Revert ByKeyElementController to use synchronous Task.FromResult
The method doesn't have any async operations, so async/await adds
unnecessary overhead.
* Fix UserPresentationFactory to use ElementContainer for element start nodes
Element start nodes reference ElementContainer (folders), not Element items.
* Add recycle bin start node access test for Element controllers
- Add WithStartElementId to UserGroupBuilder
- Add ElementRecycleBinControllerTestBase with shared test verifying
users with non-root element start nodes cannot access recycle bin
- Update all Element recycle bin tests to use the new base class
* Fix UserGroupPresentationFactory and Element test section alias
- Use ElementContainer instead of Element for start node lookups in
IReadOnlyUserGroup overload
- Use Constants.Applications.Library for Element test section alias
* Add obsolete User constructor overload for backward compatibility
- Add obsolete constructor without startElementIds parameter that delegates
to the new constructor with an empty array
- Improve XML documentation for all User constructors
* Elements: Move NoAccess property to FolderTreeItemResponseModel base class
This allows both elements and folders to indicate access status in the tree.
* Elements: Add API versioning attributes to SiblingsElementTreeController
* Elements: Add integration tests for element tree start node permissions
Add tests to verify that users with element start node restrictions can only see
and access elements within their permitted hierarchy.
* Group test files
* Remove type check from GetAllPaths overload
---------
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
* Elements: Add rollback (#21393)
* Services, repos and tests
* Endpoints for Elements versioning
* Add extra test to prove handling of pinned versions
* Renaming from PR review
* Update tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ElementVersionCleanupServiceTest.cs
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* More code clean-up after review
* Use correct deleting/deleted versions notifications
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Elements: Regenerate OpenApi.json
* Elements: Add default and granular permissions for Element controllers (#21385)
* Add Element start node support for Users and UserGroups
- Add StartElementId to UserGroup and element start nodes to User
- Add UserStartNodeFolderTreeControllerBase for tree filtering with folder support
- Update ElementTreeControllerBase to use start node filtering
- Add ElementTreeItemResponseModel.NoAccess property for "no access" items
- Add UserExtensions methods for element start node calculation
- Update User/UserGroup API models and factories
- Add database migration for startElementId column
- Add SectionAccessForElementTree authorization policy
Note: Granular element permissions deferred for future implementation
* Add element root access for default user groups on fresh install
Set StartElementId = -1 for Administrators, Writers, Editors, and
Translators user groups in DatabaseDataCreator, giving them element
root access on fresh installations (matching their content/media access).
* Add multi-type support to UserStartNodeEntitiesService
Added overloads to RootUserAccessEntities, ChildUserAccessEntities, and
SiblingUserAccessEntities that accept multiple UmbracoObjectTypes. This
enables querying for Elements and ElementContainers in a single call
rather than requiring separate queries for each type.
Also added GetAll and GetPagedChildren overloads to IEntityService and
IEntityRepository to support querying multiple object types efficiently
with a single database query.
* Add integration tests for Element start nodes with mixed hierarchy
Added UserStartNodeEntitiesServiceElementTests with a mixed hierarchy
structure containing both containers and elements at each level:
- Level 1: Containers (C1-C5) and Elements (E1-E3)
- Level 2: Child containers (C1-C1 through C1-C10) and Elements (C1-E1, C1-E2)
- Level 3: Leaf elements (C1-C1-E1 through C1-C1-E5)
This tests scenarios where containers and elements are siblings, ensuring
the access filtering works correctly for mixed-type queries.
Also refactored Content and Media tests to use a shared base class
(UserStartNodeEntitiesServiceTestsBase) to reduce code duplication.
* Add Library section for Elements
- Rename Constants.Applications.Elements to Library
- Add SectionAccessLibrary authorization policy
- Add library mapping to SectionMapper
- Grant Library section access to Administrators, Writers, and Editors on fresh install
- Update TreeAccessElements to use Library section
* Add Element tree controller authorization tests
Add integration tests for RootElementTreeController and
ChildrenElementTreeController to verify section-based
authorization works correctly for the Element tree endpoints.
* Fix ReadOnlyUserGroup not passing startElementId to constructor
The obsolete 13-parameter constructor was passing `null` instead of
the actual `startElementId` value to the next constructor, causing
user groups to appear to have no element start node access.
Also update UserFactory.ToReadOnlyGroup to pass the Description
parameter to the ReadOnlyUserGroup constructor.
* Add Element controller authorization tests
Add authorization tests for Element CRUD, Folder, RecycleBin, and Item
controllers to verify user group access permissions.
Tests cover Admin, Editor, Writer, SensitiveData, Translator, and
Unauthorized user groups for each controller endpoint.
* Re-generated OpenApi.json
* Fix Element start node handling to use ElementContainer object type
- Update UserStartNodeFolderTreeControllerBase to query both folder and
item object types when filtering by user start nodes
- Fix UserGroupPresentationFactory to use ElementContainer instead of
Element when resolving element start node IDs/keys
* Revert ByKeyElementController to use synchronous Task.FromResult
The method doesn't have any async operations, so async/await adds
unnecessary overhead.
* Fix UserPresentationFactory to use ElementContainer for element start nodes
Element start nodes reference ElementContainer (folders), not Element items.
* Add recycle bin start node access test for Element controllers
- Add WithStartElementId to UserGroupBuilder
- Add ElementRecycleBinControllerTestBase with shared test verifying
users with non-root element start nodes cannot access recycle bin
- Update all Element recycle bin tests to use the new base class
* Fix UserGroupPresentationFactory and Element test section alias
- Use ElementContainer instead of Element for start node lookups in
IReadOnlyUserGroup overload
- Use Constants.Applications.Library for Element test section alias
* Add obsolete User constructor overload for backward compatibility
- Add obsolete constructor without startElementIds parameter that delegates
to the new constructor with an empty array
- Improve XML documentation for all User constructors
* Elements: Add granular permissions for Element controllers
Add Element-specific permission actions:
- ActionElementBrowse, ActionElementNew, ActionElementUpdate, ActionElementDelete
- ActionElementPublish, ActionElementUnpublish, ActionElementMove, ActionElementCopy
Add permission infrastructure:
- ElementPermissionResource for authorization checks
- ElementPermissionHandler and ElementPermissionRequirement
- ElementPermissionService and IElementPermissionService
- ElementPermissionAuthorizer and IElementPermissionAuthorizer
- ElementGranularPermission model
- ElementPermissionMapper for user group permissions
Update Element controllers with authorization:
- Add HandleRequest pattern via CreateElementControllerBase and UpdateElementControllerBase
- Pass cultures for Publish/Unpublish authorization
- Apply authorization checks to Element CRUD and publishing operations
* Elements: Add default element permissions to user groups
Add element action permissions for Admin, Editor, Writer, and Translator
user groups in DatabaseDataCreator, mirroring the document permission pattern.
* Elements: Add current user element permissions endpoint and fix folder authorization
- Add GetElementPermissionsCurrentUserController endpoint to get current user's element permissions
- Fix ElementPermissionService to authorize both Element and ElementContainer (folders)
- Add GetElementPermissionsAsync to IUserService/UserService
- Add ElementNodeNotFound to UserOperationStatus
- Add IEntityService.GetAll overloads for multiple object types
* Elements: Move NoAccess property to FolderTreeItemResponseModel base class
This allows both elements and folders to indicate access status in the tree.
* Elements: Add default implementation to IUserService.GetElementPermissionsAsync
Adds a default throwing implementation to avoid breaking existing IUserService implementations when this method is added.
* Elements: Add API versioning attributes to SiblingsElementTreeController
* Elements: Add integration tests for element tree start node permissions
Add tests to verify that users with element start node restrictions can only see
and access elements within their permitted hierarchy.
* Add granular permissions to element rollback
* Update src/Umbraco.Core/Actions/ActionElementCopy.cs
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
* Elements: Use lowercase action aliases for consistency
Update all Element action aliases to lowercase to comply with the
IAction.Alias requirement for case-sensitive filesystems. Also rename
ActionElementNew alias from "elementNew" to "elementcreate" to match
the document action's "create" alias pattern.
* Elements: Refactor UserService permission methods to reduce duplication
Consolidate GetMediaPermissionsAsync, GetDocumentPermissionsAsync, and
GetElementPermissionsAsync into a single shared implementation via
a new private GetContentPermissionsAsync helper method.
---------
Co-authored-by: kjac <kja@umbraco.dk>
* Add element folder "item" endpoint
* Include "isTrashed" in folder response models
* Update TODOs
* Rollback a few unnecessarily breaking signature changes
* Use schema constants from #21327
* Elements: Add admin group element permissions during upgrade (#21452)
Grant the admin user group access to the element root node and all
element permissions when upgrading from a previous version. This
ensures parity with fresh installations where the admin group receives
these permissions by default.
* Elements: Fix Writer expected status codes in Element controller permission tests
Update WriterUserGroupAssertionModel to expect Forbidden for operations
that Writers don't have permission for, matching Document controller
behavior and the actual permissions assigned to the Writer group.
Changed from OK/Created to Forbidden:
- CopyElementControllerTests
- DeleteElementControllerTests
- MoveElementControllerTests
- MoveToRecycleBinElementControllerTests
- PublishElementControllerTests
- UnpublishElementControllerTests
- Folder/DeleteElementFolderControllerTests
- Folder/MoveElementFolderControllerTests
- Folder/MoveToRecycleBinElementFolderControllerTests
- RecycleBin/DeleteElementRecycleBinControllerTests
- RecycleBin/DeleteElementFolderRecycleBinControllerTests
- RecycleBin/EmptyElementRecycleBinControllerTests
* Elements: Fix duplicate column name in DocumentVersionDto index definition
The ForColumns parameter incorrectly specified PublishedColumnName twice
instead of IdColumnName and PublishedColumnName, causing SQL Server to
reject index creation with "duplicate column names" error on new installs.
* Add missing element mapper and allow deleting element types with active elements (#21483)
* Add missing element mapper and allow deleting element types with active elements
* Update src/Umbraco.Core/Services/ContentTypeService.cs
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Update src/Umbraco.Core/Services/ContentTypeService.cs
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
---------
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
* Update src/Umbraco.Core/Cache/Refreshers/Implement/ElementCacheRefresher.cs
Co-authored-by: Andy Butland <abutland73@gmail.com>
* Review comment: ReadOnlyUserGroup constructor
* Update comments in ElementEditingService
* Add Library section access to content, media, and member tree policies
* Elements: Add Elements access to data type, document type, and relation authorization policies (#21501)
Add Elements access to data type, document type, and relation authorization policies
* Amend merge from v18/dev
* Global Elements: Backoffice UI implementation (#21410)
* chore: generate new openapi types
* Added package/module for "Library"
* Added default dashboard for Library section
* [WIP] Adds "Elements" package module
Basics of the tree/menu.
* Adds entity-actions for Create and Reload
* Adds entity-action for Move To
* Adds collection workspace view
for root and folders
* Adds entity-action for Duplicate To
* "Reload Children" should only be for root & folders
* Reworked Library sidebar app
Replaced with Elements sidebar app
Removed the Library menu
* chore: generate new openapi types
* Added Item repository
* Added Reference repository
* Added Element Recycle Bin
Tree, menu, entity-actions, workspace (collection view)
* Adds "umb-element-tree-item" to identify the `isTrashed` state
* Re-added Library sidebar app
Removed Library dashboard (we'll figure it out later)
* Recycle Bin type tweaks
* [WIP] Element "Create" modal
* Reverted Element "Create" modal, to use create-options + picker
* chore: generate new openapi types
* Added Element Detail Repository
* [WIP] Element Workspace + Context
* Elements: Add workspace views for edit and info
Add edit and info workspace views to the Element workspace:
- Edit view using shared 'contentEditor' kind pattern
- Info view displaying state tag, dates, element type, and ID
- Menu structure context for tree navigation
- Split-view component for variant editing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Elements: Add save action and trash state handling
- Add Save workspace action using UmbSubmitWorkspaceAction
- Add isTrashed property to UmbElementDetailModel
- Implement trash state change handling with read-only guard
- Add recycle bin event listeners for trash/restore actions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Adds Workspace actions for Save, Publish, Scheduled Publish
* Adds Element Configuration repository
* Adds mock handle + data for Elements
* Adds Publish and Unpublish entity actions for Elements
Implements context menu actions for publishing and unpublishing elements
directly from the tree. Uses existing modals and publishing repository.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* package-lock.json update
* Adds bulk entity actions for Publish, Unpublish, Move and Trash
* Localization keys + code tweaks
* Adds reusable `emptyRecycleBin` `collectionAction` kind
* Adds `emptyRecycleBin` for Element Recycle Bin collection
* Element Recycle Bin refactoring
Working towards folder support
* Relations: exported entity-action types
* Restructured "Element Folder" code
* Restructured "Trash" entity-bulk-action code
* Adds `trashFolder` `entityAction` kind
* Adds "Trash" entity-action for Element Folders
* Tidy-up / restructuring
* [WIP] Element Picker property-editor UI
making use of an Elements property-data-source,
with Entity Picker.
* Renamed `UmbElementPropertyDatasetContext` to `UmbElementWorkspacePropertyDatasetContext`
to de-duplicate a class name clash with the underlying base class.
* Added "entity-data-picker" importmap
Exposing the "umb-input-entity-data" component
* Reworking the "Element Picker" property-editor UI
to reuse the Entity Picker internal input component
* Implemented "Element Item Data Resolver" helper
* chore: generate new openapi types
* Fixed up the mocks and types
with new Element start nodes and `noAccess` fields.
* Added UI for "Elements Start Nodes"
* Added "entity-data-picker" export to the Vite config
* Fixed Element Folder picker for "start nodes"
* Adds UI for Element's User Permissions
* Adds Element User Permission condition
Implemented the user permissions for entity actions, etc.
* Adds UI for Element's Granular Permissions
* Adds element-folder item repository
* Element Recycle Bin: implemented `isTrashed`
* Fixed mock folder data manager
* Adds move entity-action for element-folder
Implements the Move action for element folders using the
ElementService.putElementFolderByIdMove API endpoint.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix typos and element tag name mismatches in elements package
- Fix typo 'now' -> 'no' in user-permissions/types.ts
- Fix HTMLElementTagNameMap tag name to match @customElement decorator
- Fix typo 'TDOD' -> 'TODO' in element-detail.server.data-source.ts
- Fix missing 'u' prefix in element-picker tag name declaration
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Ignore local Claude settings in UI Client
* Updated workspace assign access,
to disable root access when start nodes are selected.
* Elements: Display trashed state in Element workspace info panel (#21542)
The state tag in the Element workspace info view was missing a case
for the TRASHED state, causing trashed Elements to incorrectly display
"Not created" instead of "Trashed".
* Elements: Fix folder link in recycle bin list view (#21543)
The trashed element name column always used the element workspace path
pattern, causing folders clicked in the recycle bin list view to show
"Not found". Now checks isFolder and uses the correct workspace path
pattern for folders vs elements.
* Elements: Add missing delete permission conditions to recycle bin actions (#21547)
The Empty Recycle Bin collection action and the folder delete entity
action were missing user permission conditions, making them visible
to users without delete permission.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
Co-authored-by: leekelleher <leekelleher@gmail.com>
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>
Co-authored-by: Lee Kelleher <leekelleher@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Sort at last by language name
* ensure document language picker is sorted as variant selector
* Update src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update src/Umbraco.Web.UI.Client/src/packages/documents/documents/utils.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* refactor to avoid inline methods
* transform into a function
* revert config file commit
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Prevent setting of entity Key to a new value for already persisted entities.
* Handled file based entities that have a key dependent on their path, so need to be able to have the key changed on move.
* Fixed package data update of content type to resolve failing integration test.
---------
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
* Delete GetStartContentNodes
* Delete GetStartMediaNodes
* Delete GetAllowedApplications
* Delete ClaimTypes
* Update protected recycle bin functionality to no longer used removed claim details. Added unit tests to verify behaviour.
* Fixed failing unit tests now the number of claims included is reduced.
Addressed comments from code review.
* Minor code tidy.
* Expose claim necessary for retrieving the user key.
---------
Co-authored-by: Andy Butland <abutland73@gmail.com>
description:Bump the Umbraco CMS version across all required files. Use when the user asks to bump, update, or set the version number — e.g., "bump version to 17.3.4", "set version to 18.0.0-rc", "update version". Accepts the target version as an argument.
argument-hint:<version> (e.g., 17.3.4, 18.0.0-rc)
---
# Bump Version - Umbraco CMS
Updates the Umbraco CMS version string across all files that track it.
**Do NOT use AskUserQuestion if a version argument is provided. Only ask if `$ARGUMENTS` is empty or cannot be parsed as a version.**
## Arguments
-`$ARGUMENTS` - Required: the target version string (e.g., `17.3.4`, `18.0.0-rc`)
## Files to Update
The following 5 files must be updated with the new version:
| 5 | `tests/Umbraco.Tests.AcceptanceTest/package-lock.json` | top-level `"version"` AND `packages[""].version` |
**Note**: For major version bumps (e.g., 17.x to 18.x), `src/Umbraco.Web.UI.Login/package.json` has a caret-ranged dependency on `@umbraco-cms/backoffice` (e.g., `^17.2.0`) that will need manual updating. This skill does not handle that — major bumps involve many other changes beyond version strings.
## Instructions
### 1. Parse and Validate the Version
Extract the version from `$ARGUMENTS`. It must be a valid semver-like string (e.g., `17.3.4`, `18.0.0-rc`, `17.4.0-preview.1`). If no version is provided or it cannot be parsed, ask the user for the target version.
### 2. Read the Current Version
Read `version.json` and extract the current `"version"` value. If the current version already equals the target version, report that the version is already set and stop — do not edit, stage, or commit anything.
Otherwise, display both versions:
```
Bumping version: {current} -> {target}
```
### 3. Update All Files
Update each of the 5 files listed above, replacing the old version with the new version. For each file:
- **`version.json`**: Replace the `"version"` value.
- **`package.json` files**: Replace the `"version"` value (near the top of the file).
- **`package-lock.json` files**: Replace BOTH the top-level `"version"` value AND the `"version"` inside the `"packages": { "": { ... } }` block. These are always in the first ~10 lines of the file.
Use targeted edits — do NOT rewrite entire files. Be precise to avoid changing version strings in dependency entries.
### 4. Verify
After all edits, grep for the target version value across the 5 files to confirm all updates landed correctly:
description:Automated PR code review for Umbraco CMS. Analyzes changed files for intent, impact on consumers, breaking changes, architecture compliance, and code quality. Non-interactive — outputs a full structured review. Use this skill whenever the user asks to review a branch, review a PR, check their changes for issues, analyze a diff, or validate breaking change patterns — even if they don't say "review" explicitly. Does NOT apply to writing new code, fixing bugs, refactoring, explaining architecture, writing tests, or reviewing documentation content.
argument-hint:<target-branch>
---
# PR Review - Umbraco CMS
Automated, non-interactive PR code review. Analyzes changed files for intent, impact on consumers, breaking changes, architecture compliance, and code quality.
**Do NOT use AskUserQuestion at any point. This skill runs fully autonomously.**
## Arguments
-`$ARGUMENTS` - Optional: target branch to diff against (auto-detected from PR, falls back to `origin/main`)
## Instructions
### 0. Verify GH CLI is Available
Run `gh auth status`. If it fails, read `references/gh-cli-setup.md` and present the setup instructions to the user. Do not proceed with the review.
### 1. Resolve Target Branch
Determine the target branch for comparison using this priority order:
1.**Explicit argument**: If `$ARGUMENTS` is provided and non-empty, use it as the target branch
2.**PR target branch**: If no argument, run `gh pr view --json baseRefName --jq '.baseRefName'` to detect the target branch of the current branch's open PR. If a PR exists, use `origin/{baseRefName}` as the target branch.
3.**Fallback**: If no argument and no PR found (command fails or returns empty), default to `origin/main`
Store the resolved target branch for use in subsequent steps. Log which resolution method was used (e.g., "Target branch: `origin/v18/dev` (from PR #1234)").
### 2. Load Review Standards
#### 2a. Load coding preferences
Read the coding preferences and code review scoring criteria from:
-`references/coding-preferences.md` (relative to this skill file)
Parse and internalize all rules, conventions, scoring categories, and severity definitions. These are your review criteria.
#### 2b. Load area-specific documentation
Once the changed file list is known (after step 3a), determine which areas of the codebase are touched and load the relevant documentation. Execute this sub-step between 3a and 3b. This documentation takes precedence over sibling comparison for architectural and pattern validation.
**Resolution order for each changed file:**
1.**Find the nearest `CLAUDE.md`** — walk up from the changed file's directory toward the repository root. The first `CLAUDE.md` found is the area guide for that file. Read it.
2.**Read referenced docs** — if the `CLAUDE.md` references documentation files (e.g., a `docs/` directory), use the descriptions in the `CLAUDE.md` to determine which docs are relevant to the type of code being changed, and read those. If unsure, read all referenced docs — the cost of reading is low, the cost of missing a convention is high.
3.**Follow cross-references in loaded docs** — if a loaded doc references another doc as covering a complementary or related concern, and the changed files touch that concern, read the referenced doc too. Repeat until no new relevant cross-references remain.
4.**Check for applicable skills** — review the available skills list. If a skill exists for the type of code being changed, read the skill file to understand the expected patterns, structure, and conventions it enforces. Do NOT invoke the skill — just use it as a reference for what the correct implementation should look like.
**Store all loaded documentation** for use in step 4. These docs define the authoritative patterns and conventions that the review evaluates against.
### 3. Gather Changed Files
#### 3a. Collect file list, stats, and diff
Run these git commands (where `{target}` is the resolved target branch):
Log the skip list: "Skipped {N} noise files: {comma-separated list of filenames}"
#### 3c. Read reviewable changed files
Read the full file for every reviewable changed file.
#### 3d. Track file counts
Keep track of these numbers for the review output in step 7: total changed files, noise files skipped, and reviewable files read. Also record: distinct production layers touched, distinct project directories, and total lines changed — these feed step 3e.
#### 3e. Assess PR complexity
Follow the procedure in `references/complexity-assessment.md`. Store the triggered dimensions and suggestions for step 7.
#### 3f. Classify PR scope
Classify the PR to determine which review steps are relevant:
| **Gen-only** | All reviewable files are `gen.ts` | Skip steps 5 and 6; step 4 reviews impact on other code only |
| **Docs-only** | All reviewable files are `.md` | Skip steps 5 and 6; step 4 reviews intent and readability only |
| **Test-only** | All reviewable files are in `tests/` | Skip steps 5 and 6; step 4 reviews intent, code quality, and test coverage only |
| **Config-only** | All reviewable files are `.csproj`, `.props`, `.json` config, or CI/build files | Skip step 5; step 6 checks dependency version changes only |
| **Standard** | Anything else | No skips — run all steps |
### 4. Raw Code Review
Review each changed file holistically. Think like a senior developer reading a colleague's PR. Note all findings without worrying about format or severity yet.
#### 4a. Read and reason about each file
For each changed file, reason about: What does this code do? Is it correct? What's missing — validation, error handling, notifications, cleanup, edge cases? Could this break anything for consumers?
#### 4b. Validate against documentation and patterns
Use a **docs-first** approach: classify the code by what it does, check it against documented conventions, and only fall back to sibling comparison when docs don't cover the pattern.
**Step 1 — Determine the correct approach from documentation, then check whether the PR matches**
A PR is a proposed solution, not the source of truth. This step has two parts that must happen in order — do not start part B until part A is complete.
**Part A — Before validating/judging the implementation**, determine what the correct approach is for each new class or file based on what it does. Use the documentation loaded in step 2b to identify the expected base classes, patterns, and conventions. Write down the expected approach. Classify based on what the code does, not based on what neighboring files look like.
**Part B — Now compare the PR's implementation** against the expected approach from Part A. If it deviates from the documented approach, flag it. If the documentation specifies reference examples, read those examples to verify the implementation matches.
**Pattern match is the leading finding.** If the documentation defines a pattern that fits what the code does, the first and most important finding is whether the code follows that pattern.
**Step 2 — Fall back to sibling comparison**
If the documentation does not cover the specific pattern, or for cross-cutting concerns not addressed in docs, fall back to sibling comparison:
1.**New method on existing class/interface**: Grep for the most similar existing method on the same class using `-A 80` to capture the full method body (e.g., `UpdateCurrentUserAsync` → grep for `UpdateAsync` in the same file with `-A 80`). Compare line by line for missing cross-cutting concerns: notifications/events, validation, scoping, authorization, error handling, audit logging.
2.**New TS class**: Grep for siblings by base class (`extends {BaseClass}`) or by interface (`implements {Interface}`) or by name suffix (e.g., `CurrentUserController` → grep for `UserController`). Compare for missing concerns.
3.**New CS class**: Grep for siblings by base class (`class {ClassName} : {BaseClass}`) or by interface (`class {ClassName} : {Interface}`) or by name suffix (e.g., `ManagementApiComposer` → grep for `ApiComposer`). Compare for missing concerns.
**Important:** Sibling comparison validates cross-cutting concerns, but it must not override documented conventions. If a sibling deviates from documented patterns, that sibling is wrong — do not copy its deviation.
Store your raw findings — they feed into step 7.
### 5. Impact Analysis
**Skip this step if PR scope is docs-only, test-only, or config-only.**
Follow the procedure in `references/impact-analysis.md`.
### 6. Breaking Changes Check
**Skip this step if PR scope is docs-only or test-only. If config-only, only check for dependency version changes that could break consumers.**
Follow the procedure in `references/breaking-changes.md`.
### 7. Consolidate and Output Review
Merge findings from step 4 (raw review), step 5 (impact analysis), and step 6 (breaking changes). For each finding, assign severity (Critical/Important/Suggestion) and verify it relates to changed code — not pre-existing issues. Before outputting, drop any finding about whitespace, blank lines, formatting, or comment wording. Then present the review in this exact format:
```markdown
## PR Review
**Target:**`{target_branch}` · **Based on commit:**`{head_sha}`
[If any skipped files, append: · **Skipped:** {skipped} files out of {total} total]
[If step 3f classification is not "Standard", append: · **Classified as:** {classification}]
[1–2 sentences: what this PR accomplishes , keep it as short as possible, only highlight the primary essence.]
- **Modified public API:** {changed existing interfaces/types/classes/methods}
[Omit bullet if none]
- **Affected implementations (outside this PR):** {interfaces/types/classes/methods using modified public API}
[Omit bullet if none]
- **Breaking changes:** {violations with specifics}
[Omit bullet if none]
- **Other changes:** {changes not listed above that an Umbraco user, plugin developer, or API consumer would notice — e.g., behavior changes, default value changes, error message changes, new configuration options, removed functionality. Exclude internal renames, formatting, and private implementation details.}
[Omit bullet if none]
[If step 3e triggered any dimensions, insert this block. Omit entirely if nothing triggered:]
> [!NOTE]
> **Complexity advisory** — This PR may benefit from splitting.
>
> - **{Dimension}:** {Explanation and concrete split suggestion from step 3e}
> [one bullet per triggered dimension]
>
> _This is an observation, not a blocker. The full review follows below._
---
### Critical
[Must fix before merge — security vulnerabilities, data loss, broken functionality, breaking changes without proper patterns]
[Nice to have — readability, minor refactoring, alternative approaches]
- **`{file}:{line}`**: {detail}
[Omit section if none]
---
[One of:]
## Approved
This looks good to be merged as-is, but please do a manual sanity check and testing before merging.
## Approved with Suggestions for improvement
Good to go, but please carefully consider the importance of the suggestions.
## Request Changes
Critical and important issues must be addressed first.
## Needs re-work
This is in such a bad state that the feedback of this review is not sufficient to guide improvements, the PR cannot be approved.
```
**Guidelines for the review output:**
— When reporting information, be extremely concise and sacrifice grammar for sake of concision.
- Only review code that was changed in the diff — pre-existing issues are out of scope. Focus on what compilers and linters cannot catch: behavioral side-effects (e.g., a changed default alters runtime behavior for consumers), architectural violations (e.g., a new dependency breaks layering), breaking changes for external consumers of the public API, and security implications. Leave type errors, missing imports, and broken references to CI.
- Be specific — always reference file and line number
- Explain WHY something is an issue, not just WHAT, but avoid stating the obvious.
- For complex matters, provide concrete fix suggestions, including code snippets when helpful
- Keep it constructive — the goal is to help, not gatekeep
- Don't repeat the same finding for every occurrence — mention it once and note "same pattern in {other files}"
- Focus on substantive issues only. Do NOT flag purely cosmetic or stylistic concerns. Specifically, never flag: code formatting or whitespace, comment grammar or wording, redundant-but-harmless syntax (e.g., optional chaining after a truthiness check), code duplication that doesn't cause bugs, or HTML template cosmetics. The only exception is when a stylistic issue has a concrete impact on performance or rendering. Note: missing JSDoc/documentation on public or exported APIs is a substantive finding (per coding preferences), not a cosmetic one — flag it as a Suggestion.
- For breaking changes, reference the specific pattern from the CLAUDE.md that should be applied
- Do not suggest changes that would themselves introduce breaking changes. If a suggestion would alter public API surface (e.g., changing return types, renaming public members), it is not appropriate for a PR targeting `main` within a major version. Only suggest non-breaking alternatives.
"prompt":"Review the changes in PR #22214 (branch origin/pr/22214 targeting main). This is a large frontend refactor migrating create entity actions to use entityCreateOptionAction extensions, with deprecations.",
"expected_output":"A structured review that identifies frontend deprecation patterns, flags the large PR complexity, handles 75+ files correctly, checks for breaking changes in exported components, and produces the correct output format.",
{"id":"frontend-breaking-change-awareness","text":"Checks frontend-specific breaking changes (exports, custom elements) not just backend"},
{"id":"file-references-present","text":"Findings reference specific files with line numbers"},
{"id":"no-false-critical-on-deprecations","text":"Properly deprecated code is NOT flagged as Critical breaking change"},
{"id":"no-stylistic-nitpicks","text":"Review does not flag purely cosmetic/stylistic issues (formatting, whitespace, naming conventions, comment grammar, code style preferences) unless they affect performance or rendering. Missing JSDoc on new public APIs is NOT a stylistic issue — it is a legitimate finding."},
{"id":"manifest-alias-rename-detected","text":"Alias renames (CreateOptions → Create) flagged as Critical breaking change"},
{"id":"non-exported-deletions-dismissed","text":"Deleted action classes NOT flagged as breaking (verified against package.json exports)"},
{"id":"noise-files-filtered","text":"Does not review noise files (generated files, lock files, etc.)"},
{"id":"complexity-advisory-triggers","text":"Review includes a complexity/split advisory for the large 75+ file scope"}
]
},
{
"id":1,
"name":"pr-21672-small-frontend-bugfix",
"prompt":"Review the changes in PR #21672 (branch origin/pr/21672 targeting main). This is a small 4-file frontend bugfix implementing tab validation badges in the block editor.",
"expected_output":"A clean review that correctly identifies this as a small focused bugfix, avoids false positives, and either approves or approves with minor suggestions.",
"pr_number":21672,
"pr_branch":"origin/pr/21672",
"base_branch":"origin/main",
"files":[],
"assertions":[
{"id":"complexity-advisory-absent","text":"Review does NOT include a complexity/split advisory"},
{"id":"no-false-breaking-changes","text":"Review does not flag breaking changes"},
{"id":"proportionate-verdict","text":"Verdict is 'Request Changes'"},
{"id":"concise-review","text":"Review output is under 200 lines"},
{"id":"no-stylistic-nitpicks","text":"Review does not flag purely cosmetic/stylistic issues (formatting, whitespace, naming conventions, comment grammar, code style preferences) unless they affect performance or rendering. Missing JSDoc on new public APIs is NOT a stylistic issue — it is a legitimate finding."}
]
},
{
"id":2,
"name":"pr-22217-small-backend-webhook",
"prompt":"Review the changes in PR #22217 (branch origin/pr/22217 targeting v18/dev). This is a tiny 3-file backend change to the default webhook payload type.",
"expected_output":"A concise review that correctly resolves v18/dev as target branch, handles the small change proportionately, and considers the behavioral impact of changing a default value.",
"pr_number":22217,
"pr_branch":"origin/pr/22217",
"base_branch":"origin/v18/dev",
"files":[],
"assertions":[
{"id":"correct-target-branch","text":"Review references 'v18/dev' as the target branch (not 'main')"},
{"id":"default-value-change-noted","text":"Review discusses the behavioral impact of changing the default payload type"},
{"id":"proportionate-review","text":"Review output is under 150 lines"},
{"id":"no-stylistic-nitpicks","text":"Review does not flag purely cosmetic/stylistic issues (formatting, whitespace, naming conventions, comment grammar, code style preferences) unless they affect performance or rendering. Missing JSDoc on new public APIs is NOT a stylistic issue — it is a legitimate finding."},
{"id":"ignores-preexisting-issues","text":"Does NOT flag the ~30 builder extension methods with Legacy defaults (pre-existing, not changed in the PR)"},
{"id":"side-effect-detection","text":"Flags stale WebhookSettings.cs docs as a side-effect of the constant value change"},
{"id":"consumer-identification","text":"Identifies affected consumers outside the PR (WebhookSettings, UmbracoBuilder, or WebhookEventCollectionBuilderExtensions)"}
"prompt":"Review the changes in PR #22268 (branch origin/pr/22268 targeting main). This is a 29-file frontend feature adding a current user workspace modal.",
"expected_output":"A review of a medium-sized new feature PR. Should assess the new code for architectural compliance, check for breaking changes (new exports, custom elements), and evaluate code quality without flagging pre-existing issues.",
"pr_number":22268,
"pr_branch":"origin/pr/22268",
"base_branch":"origin/main",
"files":[],
"assertions":[
{"id":"complexity-advisory-triggers","text":"Review includes a complexity/split advisory (3 layers: Core, API, Frontend across 27+ files)"},
{"id":"breaking-changes-on-interface-additions","text":"Flags new interface methods without default implementations as breaking changes (Pattern 3)"},
{"id":"no-stylistic-nitpicks","text":"Review does not flag purely cosmetic/stylistic issues unless they affect performance or rendering. Missing JSDoc on new public APIs is NOT a stylistic issue — it is a legitimate finding."},
{"id":"diff-scoped","text":"All findings reference code that was changed in the diff, not pre-existing issues"},
{"id":"new-feature-assessed","text":"Review assesses the new feature's architecture, patterns, or integration approach — not just absence of bugs"},
{"id":"no-false-notification-finding","text":"Review does NOT flag UpdateCurrentUserAsync as missing UserSavingNotification/UserSavedNotification — the sibling UpdateAsync also does not publish these notifications, so flagging their absence would be a false positive"}
"prompt":"Review the changes in PR #22215 (branch origin/pr/22215 targeting main). This is a 2-file frontend feature adding user management to the user group workspace.",
"expected_output":"A review that catches the architecture violation: the workspace context directly imports and calls UserService and UserGroupService (generated API clients) instead of going through a repository. In the Umbraco backoffice, workspace contexts access data via repositories, not by calling API services directly. The review should flag this as a significant architecture issue and request changes.",
"pr_number":22215,
"pr_branch":"origin/pr/22215",
"base_branch":"origin/main",
"files":[],
"assertions":[
{"id":"service-bypass-detected","text":"Review flags that the workspace context directly imports/calls UserService or UserGroupService instead of using a repository"},
{"id":"repository-pattern-recommended","text":"Review recommends using the repository pattern (going through a repository/data-source layer) rather than calling API services directly from the workspace context"},
{"id":"verdict-request-changes","text":"Verdict is 'Request Changes' (the architecture violation warrants requesting changes, not just approving with suggestions)"},
{"id":"no-stylistic-nitpicks","text":"Review does not flag purely cosmetic/stylistic issues (formatting, whitespace, naming conventions, comment grammar, code style preferences) unless they affect performance or rendering. Missing JSDoc on new public APIs is NOT a stylistic issue — it is a legitimate finding."},
{"id":"no-false-breaking-changes","text":"Review does not flag breaking changes (this PR only adds new code, no public API is removed or modified)"}
This document describes how to detect and validate breaking changes during PR review. It covers both backend (.NET) and frontend (TypeScript/Lit) patterns.
---
## Version Detection
**Always read `version.json`** at the repository root to determine the current major version. This drives the obsolete removal target calculation:
- Current major version: read from `version.json` → `version` field (e.g., `"17.4.0-rc"` → major version `17`)
- Obsolete removal target: `current + 2` (e.g., if current is 17, removal is scheduled for Umbraco 19)
- Format: `[Obsolete("... Scheduled for removal in Umbraco {current+2}.")]`
---
## Backend (.NET) Breaking Changes
### What Constitutes a Breaking Change
Any of these on a `public` or `protected` member:
- Removing or renaming a class, interface, struct, record, or enum
- Removing or renaming a method, property, or field
- Changing a method signature (parameters, return type)
- Adding required parameters to an existing method
- Adding methods to a public interface (without default implementation)
- Changing a constructor signature on a public class
- Removing or changing enum values
- Changing type hierarchy (base class, implemented interfaces)
- [ ] Old constructor has `[Obsolete]` attribute with correct removal version
- [ ] Old constructor calls new constructor via `: this(...)`
- [ ]`StaticServiceProvider.Instance.GetRequiredService<T>()` used for new params only
- [ ] DI registration uses the NEW constructor (old is for external consumers only)
- [ ] Removal version is `{current_major + 2}`
**Common mistakes to flag:**
- Removing the old constructor entirely (breaking change!)
- Old constructor NOT calling new constructor (code duplication)
- Wrong removal version in `[Obsolete]`
- Missing `StaticServiceProvider` resolution for new dependencies
- DI registration still using the old constructor
### Pattern 2: Obsolete Method + New Overload
When a method signature needs to change, add the new overload and obsolete the old.
**Correct pattern:**
```csharp
[Obsolete("Use the overload taking all parameters. Scheduled for removal in Umbraco 19.")]
publicvoidDoThing(stringname)
=>DoThing(name,extraParam:null);
publicvoidDoThing(stringname,string?extraParam)
{
// Real implementation here
}
```
**Validation checklist:**
- [ ] Old method has `[Obsolete]` attribute with correct removal version
- [ ] Old method calls new method, providing defaults for new parameters
- [ ] All internal callers updated to use the new method
- [ ] No internal code references the obsolete method (except the delegation)
### Pattern 3: Default Interface Implementation
When adding methods to a public interface, provide a default implementation.
**Correct pattern:**
```csharp
publicinterfaceIMyService
{
voidExistingMethod();
// New method with default implementation
voidNewMethod(stringparam)
=>ExistingMethod();// delegate to existing if possible
}
```
**Strategies for defaults (in order of preference):**
1. Use existing interface methods to satisfy the contract
2. Return a sensible default (empty collection, null, etc.)
3. Throw `NotImplementedException` if no reasonable default exists
**Validation checklist:**
- [ ] New interface method has a default implementation
- [ ] TODO comment present: `// TODO (V{next-major}): Remove the default implementation when {obsolete method} is removed.`
- [ ] Default implementation is functionally correct (even if not optimal)
- [ ] If `StaticServiceProvider` is used in default impl, noted as temporary
### Obsolete Attribute Validation
For any `[Obsolete]` attribute found in changed code:
1.**Format**: Must contain `"Scheduled for removal in Umbraco {version}."`
2.**Version**: Must be `current_major + 2` (read from `version.json`)
3.**Pragma**: Where obsolete members must call each other, `#pragma warning disable CS0618` / `#pragma warning restore CS0618` must be present
### Internal Caller Check
After finding obsolete patterns, verify:
- Search the codebase for usages of the obsolete member
- **No internal code** (inside `src/`) should reference obsolete members
- Only the obsolete member's own delegation (calling the new version) is acceptable
- External consumers (outside the repo) get the deprecation period to migrate
---
## Frontend (TypeScript/Lit) Breaking Changes
The backoffice is published as `@umbraco-cms/backoffice` with 140+ named exports. Plugin developers depend on this public API surface.
**Critical frontend rule (does not apply to backend .NET where `public`/`protected` visibility determines the API surface): only symbols reachable through the `package.json` `exports` field are public API.** Anything not exported — whether classes, functions, constants, types, or entire files — is an internal implementation detail, even if other internal code imports it. Removing or changing unexported frontend symbols is not a breaking change. Before flagging a frontend deletion or rename as breaking, verify the symbol is reachable via `package.json` exports. If it is not, do not flag it.
### Custom Elements (Web Components)
**Breaking changes:**
- Renaming or removing a registered custom element tag (`umb-*`)
- Removing elements from `HTMLElementTagNameMap`
- Removing or changing `@property()` decorated fields on exported components
- Removing event emissions (checked via `this.dispatchEvent`)
- Removing CSS custom properties (`@cssprop` in JSDoc)
- Removing CSS parts (`@csspart` in JSDoc)
**How to detect:**
- Check diff for removed `@customElement('umb-...')` decorators
- Check diff for removed `@property()` fields on exported components
- Check diff for removed entries in `HTMLElementTagNameMap` declarations
### Exported Types/Interfaces
**Breaking changes:**
- Removing exports from `package.json``exports` field
- Changing the shape of exported interfaces (removing properties, changing types)
- Renaming exported types (consumers import by name)
- Removing union type members
- Changing generic type parameter constraints
**How to detect:**
- Check if `package.json``exports` field is modified
- Check diff for removed `export` statements
- Check diff for changed interface/type shapes
### Manifest/Extension System
**Breaking changes:**
- Renaming a manifest `alias` value — plugin developers reference aliases by string in conditions, overwrites, and extension registry lookups. Alias renames are not caught by the compiler since they are string-based. A renamed alias silently breaks any plugin that references the old string.
- Removing support for a manifest `type` that plugins use
- Changing manifest `alias` resolution or validation
- Removing or renaming manifest `kind` types
- Changing extension bundle structure
**How to detect:**
- **Alias renames**: Compare `alias:` values in manifest files before and after. Changed alias strings are Critical — the old alias should be preserved as a deprecated entry.
- Search for changes to manifest type definitions
- Check for removed or renamed manifest kinds
### Context API
**Breaking changes:**
- Removing context tokens from exports
- Changing the shape of data provided by a context
- Removing context provider/consumer mechanisms
**How to detect:**
- Check for removed context token exports
- Check for changes to context provider classes
### Controllers/Lifecycle
**Breaking changes:**
- Changing controller base class inheritance requirements
- Removing controller lifecycle hooks
- Breaking cleanup mechanisms in `disconnectedCallback()`
### Observable/State
**Breaking changes:**
- Removing observable properties from the public API
- Changing observable emission patterns
### npm Publishing
**Breaking changes:**
- Changing version constraints that exclude previously-supported versions
- Adding incompatible peer dependency constraints
**How to detect:**
- Check if `package.json``peerDependencies` or `dependencies` changed
- Verify version ranges are not narrowed
---
## Reporting Breaking Changes
When a breaking change is detected, report:
1.**What**: The specific change and which public symbol is affected
2.**Pattern**: Which mitigation pattern should be applied (Pattern 1, 2, or 3 for backend)
3.**Severity**: Critical (no mitigation present) or Important (mitigation present but incorrect)
4.**Fix**: Concrete code suggestion showing the correct pattern
If no breaking changes are detected, state: "No breaking changes detected."
- **Log messages**: Technical, detailed, with context
- Include correlation IDs and relevant data in logs
---
## Security
- **Always check for security issues** using OWASP Top 10 as baseline
- Flag potential vulnerabilities immediately
- Suggest secure alternatives when spotting risky patterns
- Apply principle of least privilege
---
## Immutability
- Prefer **immutability** by default
- Allow internal properties to be mutated, as long as they are not direct references coming from the outside
---
## Nullability
- **TypeScript / JavaScript**
- Prefer `undefined` for optional/omitted values (e.g., optional parameters, props, and fields)
- Use `null` only when the domain model explicitly encodes "no value" or "not set" (e.g., `string | null` from APIs/DB), and be consistent with existing types
- Avoid mixing `null` and `undefined` for the same concept within the same model or API surface
- **C#**
- use nullable types (e.g., `string?`, `int?`) where absence is valid
- Prefer domain modeling (value objects, options/results, empty collections) over `null` where appropriate, but respect existing conventions in the codebase
---
## C# Specific
- use Notification pattern (not C# events), Composer pattern (DI registration), Scoping with `Complete()`, Attempt pattern for operation results.
---
## Architecture
- Follow **Clean Architecture** principles
- **Fail-fast** principle: detect and report errors as early as possible
- Within the established layered architecture (Core/Infrastructure/Web/API), organize code by feature inside each layer where practical, while preserving dependency direction
- One class per file
- Avoid N+1 queries
- Profile before optimizing non-critical paths
### Type Hierarchy Consistency
When parallel model types have inconsistent relationships to a shared base type:
**TypeScript**: manipulations via `Omit`, `Pick`, intersection overrides, or workarounds like `as unknown as` / double-casts to bridge type mismatches.
**C#**: hiding base members with `new` to change types, explicit interface implementations to mask mismatches, or downcasting base return types in derived classes.
- **Do NOT suggest** the PR code should deviate from its base type to match a sibling that already deviates. Copying the deviation spreads the problem.
- **Do flag** the architectural inconsistency: parallel models should share a compatible base contract. The model that manipulates or deviates from the base type is the one that needs attention — not the one that extends it correctly.
- **Frame the suggestion** as: "These related models have inconsistent type hierarchies. `{deviating type}` manipulates the base contract of `{base type}`, which forces shared consumers like `{shared utility}` to require a shape that conforming subtypes can't satisfy."
---
## Code Style
- Follow standard naming conventions for the language (C# or JS/TS)
- Keep components small and focused on a single responsibility
- Prefer early returns
- Small functions
- No nested ternaries
---
## Severity Levels
| Severity | Meaning |
|----------|---------|
| **Critical** | Must fix before merge — security vulnerabilities, data loss risks, broken functionality |
For any file where the whitespace-ignored diff is less than **half** the full diff size (and the full diff is over 50 lines), that file has significant formatting changes mixed with logic. Flag it with a split suggestion: "File(s) {list} contain significant formatting changes mixed with logic. Consider a separate formatting-only commit or PR to keep the functional diff reviewable."
## Multi-project scope check
Skip this section entirely if ALL production files reside in a single project directory or if the PR is docs-only, test-only, dependency-bump-only, or rename-only.
Otherwise, flag any dimension that applies:
| Dimension | Condition | Suggestion |
|---|---|---|
| **Size** | 30+ files OR 1500+ lines, spanning 2+ projects | "If changes in {projectA} and {projectB} are independently functional, they could be separate PRs." |
| **Mixed intent** | 2+ intent categories (new feature, bugfix, refactor, dependency update) with 15+ files or 3+ projects | "Consider extracting the {secondary intent} into a separate PR." |
Intent categories — detect from diff characteristics, not commit messages:
- **New feature**: new files or new `public`/`export` declarations
- **Bug fix**: small targeted edits, no new files (don't co-flag with new feature)
- **Refactor**: file renames, symbols moved but logic unchanged
- **Dependency update**: changes to `.csproj`, `Directory.Packages.props`, `package.json`
This document describes how to perform impact analysis during PR review. The goal is to look beyond the diff to understand how changes affect consumers in other parts of the codebase.
---
## 1. Extract Changed Public Symbols
Scan the diff output for changes to public API surface:
### Backend (.NET)
Look for added, modified, or removed lines containing:
- **Notification handlers**: if a notification type changed, search for `INotificationHandler<NotificationTypeName>` and `INotificationAsyncHandler<NotificationTypeName>`
- **Interface implementations**: if an interface changed, search for `: IInterfaceName` or `IInterfaceName,`
### Excluding the Changed File
When reporting consumers, exclude files that are part of the PR's changes (they're already being reviewed). The interesting consumers are those **outside** the PR that may be affected.
---
## 3. Check Dependency Flow Direction
The Umbraco architecture enforces strict unidirectional dependencies:
```
Api.Management / Api.Delivery (depend on Api.Common)
- **Swashbuckle.AspNetCore.SwaggerUI** - Swagger UI for API documentation
- **Lucene.NET** - Full-text search via Examine
- **ImageSharp** - Image processing
@@ -198,7 +199,7 @@ Use the format: `Area: Description (closes #IssueID)`
- Describe the change and its impact
- Be specific, not vague (describe "a golden retriever" not just "a dog")
**Issue Linking**: Add `(closes #IssueID)` to auto-close linked issues on merge.
**Issue Linking**: Add `(closes #IssueID)` to the title for readability, AND include a closing keyword on its own line in the PR body (e.g., `Fixes #IssueID`) so GitHub actually auto-links and auto-closes the issue on merge. GitHub only parses closing keywords (`closes`, `fixes`, `resolves`) from the PR body or commit messages — the title suffix is cosmetic and does **not** trigger auto-close on its own.
### Commit Messages
@@ -227,9 +228,11 @@ Project ownership is distributed across teams. Check individual project director
1.**Layered Architecture with Dependency Inversion**
- Core defines contracts (interfaces)
- Infrastructure implements contracts
- Infrastructure implements contracts that need Infrastructure-owned machinery
- Web/APIs consume implementations via DI
**Where service implementations live**: Services whose dependencies are satisfiable from Core interfaces alone (repositories, scope, config, other Core services) live in `Umbraco.Core/Services/` — this covers the majority of domain services (`MemberService`, `ContentService`, `MediaService`, `ContentTypeService`, `EntityService`, `AuditService`, `ExternalMemberService`, etc.). Service implementations only live in `Umbraco.Infrastructure/Services/Implement/` when they genuinely need Infrastructure concerns — Examine indexes (`ContentSearchService`, `MediaSearchService`, `IndexedEntitySearchService`), log files (`LogViewerRepository`), packaging internals (`PackagingService`), webhook firing (`WebhookFiringService`), distributed-job coordination (`DistributedJobService`). When adding a new service, default to Core and only move to Infrastructure if a concrete dependency forces it.
2.**Interface-First Design**
- All services defined as interfaces in Core
- Enables testing, polymorphism, extensibility
@@ -364,16 +367,27 @@ public interface IMyService
### Centralized Package Management
**All NuGet package versions** are centralized in `Directory.Packages.props`. Individual projects do NOT specify versions.
**NuGet package versions** are centralized in `Directory.Packages.props`. There are two `Directory.Packages.props` files in the source tree, with multi-level merging enabled so the test file inherits from the root:
| File | Scope |
|------|-------|
| `Directory.Packages.props` (root) | Production source code packages — referenced by all `src/**` projects |
| `tests/Directory.Packages.props` | Test-only packages (NUnit, Moq, Bogus, BenchmarkDotNet, etc.) — adds entries on top of the inherited root file |
When updating dependencies, decide which file the package belongs in:
- A package used only by test projects → `tests/Directory.Packages.props`
- A package used by any production project (or by both production and tests) → root `Directory.Packages.props`
```xml
<!-- Individual projects reference WITHOUT version -->
**Opt-out**: `src/Umbraco.Web.UI/Umbraco.Web.UI.csproj` sets `<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>` and specifies versions inline (for `Microsoft.EntityFrameworkCore.Design`, `Microsoft.Build.Tasks.Core`, `Microsoft.ICU.ICU4C.Runtime`, etc.). Update those versions directly in that csproj when bumping. Two further `Directory.Packages.props` files exist under `templates/` for the project/extension templates and have their own version sets — keep `Microsoft.AspNetCore.OpenApi` aligned between the root file and `templates/UmbracoExtension/`.
The backoffice (`Umbraco.Web.UI.Client`) is published to npm as **`@umbraco-cms/backoffice`** with a plugin architecture:
When a PR changes Management API controllers or models, the `OpenApi.json` file in the Management API project must be updated:
#### Architecture Overview
1. Run the Umbraco instance locally
2. Open Swagger UI and navigate to the swagger.json link (e.g. `https://localhost:44339/umbraco/swagger/management/swagger.json`)
3. Copy the full JSON content and paste it into `src/Umbraco.Cms.Api.Management/OpenApi.json`
- **Multi-workspace structure**: Subprojects in `src/libs/*`, `src/packages/*`, `src/external/*`
- **Export model**: All exports defined in root `package.json` → `./exports` field
- **Importmap-driven runtime**: Dependencies provided at runtime via importmap (single source of truth)
- **Build-time types**: TypeScript types come from npm peerDependencies
- **Plugin model**: Developers create plugins that import from `@umbraco-cms/backoffice/*` exports
**Important**: Commit only the substantive changes — not IDE-applied formatting (whitespace, reordering, etc.). Extraneous formatting diffs make PRs harder to review and merge-ups more error-prone.
#### Dependency Hoisting Strategy
### Backoffice npm Package
When building for npm (`npm pack`), the `cleanse-pkg.js` script hoists subproject dependencies to root `peerDependencies` with intelligent version range conversion:
**Version Range Logic** (uses `semver` package):
1. **Pre-release (0.x.y)**: Convert to explicit range
- Input: `^0.85.0` or `0.85.0`
- Output: `>=0.85.0 <1.0.0`
- Rationale: Pre-release caret only allows patch updates, explicit range allows minor upgrades within 0.x.x
- Example: Plugin can use `@hey-api/openapi-ts@0.91.1` while backoffice uses `0.85.0`
2. **Stable with caret (^X.Y.Z where X ≥ 1)**: Keep as-is
- Input: `^3.3.1`
- Output: `^3.3.1` (unchanged)
- Rationale: Caret already implements correct semantics for stable versions
3. **Stable exact versions (X.Y.Z where X ≥ 1)**: Add caret
- Input: `3.16.0`
- Output: `^3.16.0`
- Rationale: Normalizes to conventional semver format
#### Key Dependencies
**Runtime via importmap** (types available from peerDependencies):
- Uses `semver.minVersion()` for robust version range parsing
- Generates single source of truth for importmap versions
The backoffice is published to npm as `@umbraco-cms/backoffice`. Runtime dependencies are provided via importmap; npm peerDependencies provide types only. For full details on dependency hoisting, version range logic, and plugin development, see `/src/Umbraco.Web.UI.Client/CLAUDE.md` → "npm Package Publishing".
### Known Limitations
@@ -486,6 +456,94 @@ Plugin developers should:
---
## 7. CI/CD — Claude AI Assistant
Two GitHub Actions workflows powered by `anthropics/claude-code-action@v1`. Advisory only — does not block merging.
### Workflows
| File | Trigger | Purpose |
|------|---------|---------|
| `claude-review.yml` | `pull_request: [opened, ready_for_review]` | Auto-review every non-draft PR using the `umb-review` skill |
| `claude.yml` | `@claude` comments, issue assign/label | Interactive assistant for PRs and issues |
### Auto-Review (`claude-review.yml`)
Runs the full `.claude/skills/umb-review/SKILL.md` procedure on every newly opened or un-drafted PR. Produces inline comments per finding and one summary comment with a verdict. Skips draft PRs. No turn limit.
### Interactive (`claude.yml`)
Responds to `@claude` mentions on PRs and issues. The trigger phrase is stripped before Claude sees the message, so:
- `@claude review` → light review using `gh pr diff` (not the umb-review skill)
- `@claude fix ...` → implements a fix on a new branch
- `@claude help` → answers questions about the codebase
- `@claude label` → applies labels
- `@claude` (empty) → defaults to `review` on PRs, `help` on issues
Also triggers on issue assignment to `claude` or adding the `claude` label. Gated: only runs when `@claude` appears in the comment/issue body. Max 25 turns.
**On Issues** (based on content): same `area/*` and `category/*` labels, plus `affected/v14` through `affected/v17` and `affected/backoffice`.
Labels are only added, never removed. Claude applies only labels it is confident about.
### Key Implementation Notes
- **Checkout required** — the action internally runs `git fetch origin main` for trusted file restoration. Without `actions/checkout`, it fails with `fatal: not a git repository`.
- **`id-token: write` permission** — required for OIDC token exchange with the Claude GitHub App.
- **Trigger phrase stripping** — the action strips `@claude` from comments before passing to Claude. Prompts must reference commands without the prefix (e.g., `review` not `@claude review`).
- **PR number injection** — the interactive workflow injects the PR/issue number into the prompt via `${{ github.event.issue.number }}` since Claude can't discover it from `gh pr view` when checked out on `main`.
---
## 8. Code Comment Policy
**Default to no comment.** Applies to all code in this repository — C#, TypeScript, Razor, build scripts. Well-named identifiers and small functions are the primary form of self-documentation; comments are a fallback for the rare cases where the code itself cannot carry the meaning.
### When NOT to comment
- **Don't restate what the code does.** A line calling `resetState()` does not need `// Reset state`. A method named `validateInput` does not need `// Validate input`.
- **Don't narrate a sequence of calls.** If three lines run in order, the order is in the code — don't paraphrase it above.
- **Don't reference the current task, fix, callers, or PR.** No `// Fix for X`, `// Used by Y`, `// Added for the Z flow`, `// See PR #1234`. That belongs in commit messages and PR descriptions; in source it rots as the codebase evolves.
### When a comment IS justified
Write a comment only when **removing it would leave a future reader confused**. Concretely:
- **A non-obvious WHY.** A hidden constraint, business rule, or ordering requirement that is not visible from the code.
- **A workaround for a specific bug or platform quirk.** Link the issue (`(#21996)`, `https://...`) so the comment can be deleted once the upstream fix lands.
- **A subtle invariant** that the type system or method names do not enforce.
- **An edge case the code intentionally handles** that would surprise a reader (e.g. "must run before X because Y").
- **API documentation** — XML doc comments on C# members, JSDoc on exported TypeScript symbols. Required for the public contract; still keep them concise.
### TODOs
Allowed, but cheap to write and cheaper to leave behind. Keep them short and trackable: `// TODO (V19): remove once obsolete overload is gone` or `// TODO: pagination [NL]`. A TODO should have an author or a version trigger.
---
## Quick Reference
### Essential Commands
@@ -507,6 +565,16 @@ dotnet format
dotnet pack -c Release
```
### Integration Test Database Configuration
Integration tests are configured in `tests/Umbraco.Tests.Integration/appsettings.Tests.json`.
The `Tests:Database:DatabaseType` setting controls which database is used:
- `"SQLite"` (default) - No external dependencies
- `"LocalDb"` - Uses SQL Server LocalDB, required for SQL Server-specific tests (e.g., page-level locking, `sys.dm_tran_locks`)
SQL Server-specific tests use `BaseTestDatabase.IsSqlite()` to skip when running on SQLite.
### Key Projects
| Project | Type | Description |
@@ -534,6 +602,8 @@ For detailed information about individual projects, see their CLAUDE.md files:
**Important**: When working on backoffice client code (anything under `src/Umbraco.Web.UI.Client/`), read `/src/Umbraco.Web.UI.Client/CLAUDE.md` first. It contains action-specific checklists (deprecation, testing, security, etc.) that are not duplicated here.
=> type.Namespace?.StartsWith("MyProject") is true;
OpenAPI transformers are scoped per-document. To customize a document, implement `IOpenApiDocumentTransformer`, `IOpenApiOperationTransformer`, or `IOpenApiSchemaTransformer` and register with your OpenAPI options.
**Decision**: Make `SchemaIdHandler`, `OperationIdHandler`, etc. virtual.
**Why**: Management API and Delivery API have different schema ID requirements. Virtual methods allow override without rewriting the entire handler.
**Example**: Management API might prefix all schemas with "Management", Delivery API with "Delivery".
With Microsoft.AspNetCore.OpenApi, transformers are configured per OpenAPI document. This means custom transformers only apply to the documents they're registered with, not globally. Each API (Management, Delivery) configures its own transformers via `ConfigureUmbracoOpenApiOptionsBase` subclasses.
=>$"{apiDesc.GroupName}_{apiDesc.ActionDescriptor.AttributeRouteInfo?.Template ?? apiDesc.ActionDescriptor.RouteValues["controller"]}_{(apiDesc.ActionDescriptor.RouteValues.TryGetValue("action", out var action) ? action : null)}_{apiDesc.HttpMethod}";
$"You can find out more about the {DeliveryApiConfiguration.ApiTitle} in [the documentation]({DeliveryApiConfiguration.ApiDocumentationContentArticleLink}).";
Description=$"You can find out more about the {DeliveryApiConfiguration.ApiTitle} in [the documentation]({DeliveryApiConfiguration.ApiDocumentationContentArticleLink})."
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.