diff --git a/src/Umbraco.Core/Services/IContentPublishOperationService.cs b/src/Umbraco.Core/Services/IContentPublishOperationService.cs
new file mode 100644
index 0000000000..9c173d06f9
--- /dev/null
+++ b/src/Umbraco.Core/Services/IContentPublishOperationService.cs
@@ -0,0 +1,213 @@
+// src/Umbraco.Core/Services/IContentPublishOperationService.cs
+using System.ComponentModel;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Persistence.Querying;
+
+namespace Umbraco.Cms.Core.Services;
+
+///
+/// Service for content publishing operations (publish, unpublish, scheduled publishing, branch publishing).
+///
+///
+///
+/// Implementation Note: Do not implement this interface directly.
+/// Instead, inherit from which provides required
+/// infrastructure (scoping, repository access, auditing). Direct implementation
+/// without this base class will result in missing functionality.
+///
+///
+/// This interface is part of the ContentService refactoring initiative (Phase 5).
+/// It extracts publishing operations into a focused, testable service.
+///
+///
+/// Note: This interface is named IContentPublishOperationService to avoid
+/// collision with the existing IContentPublishingService which is an API-layer orchestrator.
+///
+///
+/// Versioning Policy: This interface follows additive-only changes.
+/// New methods may be added with default implementations. Existing methods will not
+/// be removed or have signatures changed without a 2 major version deprecation period.
+///
+///
+public interface IContentPublishOperationService : IService
+{
+ #region Publishing
+
+ ///
+ /// Publishes a document.
+ ///
+ /// The document to publish.
+ /// The cultures to publish. Use "*" for all cultures or specific culture codes.
+ /// The identifier of the user performing the action.
+ /// The publish result indicating success or failure.
+ ///
+ /// When a culture is being published, it includes all varying values along with all invariant values.
+ /// Wildcards (*) can be used as culture identifier to publish all cultures.
+ /// An empty array (or a wildcard) can be passed for culture invariant content.
+ /// Fires ContentPublishingNotification (cancellable) before publish and ContentPublishedNotification after.
+ ///
+ PublishResult Publish(IContent content, string[] cultures, int userId = Constants.Security.SuperUserId);
+
+ ///
+ /// Publishes a document branch.
+ ///
+ /// The root document of the branch.
+ /// Options for force publishing unpublished or re-publishing unchanged content.
+ /// The cultures to publish.
+ /// The identifier of the user performing the operation.
+ /// Results for each document in the branch.
+ /// The root of the branch is always published, regardless of .
+ IEnumerable PublishBranch(IContent content, PublishBranchFilter publishBranchFilter, string[] cultures, int userId = Constants.Security.SuperUserId);
+
+ #endregion
+
+ #region Unpublishing
+
+ ///
+ /// Unpublishes a document.
+ ///
+ /// The document to unpublish.
+ /// The culture to unpublish, or "*" for all cultures.
+ /// The identifier of the user performing the action.
+ /// The publish result indicating success or failure.
+ ///
+ /// By default, unpublishes the document as a whole, but it is possible to specify a culture.
+ /// If the content type is variant, culture can be either '*' or an actual culture.
+ /// If the content type is invariant, culture can be either '*' or null or empty.
+ /// Fires ContentUnpublishingNotification (cancellable) before and ContentUnpublishedNotification after.
+ ///
+ PublishResult Unpublish(IContent content, string? culture = "*", int userId = Constants.Security.SuperUserId);
+
+ #endregion
+
+ #region Document Changes (Advanced API)
+
+ ///
+ /// Commits pending document publishing/unpublishing changes.
+ ///
+ /// The document with pending publish state changes.
+ /// The identifier of the user performing the action.
+ /// Optional state dictionary for notification propagation across orchestrated operations.
+ /// The publish result indicating success or failure.
+ ///
+ ///
+ /// This is an advanced API. Most consumers should use or
+ /// instead.
+ ///
+ ///
+ /// Call this after setting to
+ /// or .
+ ///
+ ///
+ /// This method is exposed for orchestration scenarios where publish/unpublish must be coordinated
+ /// with other operations (e.g., MoveToRecycleBin unpublishes before moving).
+ ///
+ ///
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ PublishResult CommitDocumentChanges(IContent content, int userId = Constants.Security.SuperUserId, IDictionary? notificationState = null);
+
+ #endregion
+
+ #region Scheduled Publishing
+
+ ///
+ /// Publishes and unpublishes scheduled documents.
+ ///
+ /// The date to check schedules against.
+ /// Results for each processed document.
+ IEnumerable PerformScheduledPublish(DateTime date);
+
+ ///
+ /// Gets documents having an expiration date before (lower than, or equal to) a specified date.
+ ///
+ /// The date to check against.
+ /// Documents scheduled for expiration.
+ IEnumerable GetContentForExpiration(DateTime date);
+
+ ///
+ /// Gets documents having a release date before (lower than, or equal to) a specified date.
+ ///
+ /// The date to check against.
+ /// Documents scheduled for release.
+ IEnumerable GetContentForRelease(DateTime date);
+
+ #endregion
+
+ #region Schedule Management
+
+ ///
+ /// Gets publish/unpublish schedule for a content node by integer id.
+ ///
+ /// Id of the content to load schedule for.
+ /// The content schedule collection.
+ ContentScheduleCollection GetContentScheduleByContentId(int contentId);
+
+ ///
+ /// Gets publish/unpublish schedule for a content node by GUID.
+ ///
+ /// Key of the content to load schedule for.
+ /// The content schedule collection.
+ ContentScheduleCollection GetContentScheduleByContentId(Guid contentId);
+
+ ///
+ /// Persists publish/unpublish schedule for a content node.
+ ///
+ /// The content item.
+ /// The schedule to persist.
+ void PersistContentSchedule(IContent content, ContentScheduleCollection contentSchedule);
+
+ ///
+ /// Gets a dictionary of content Ids and their matching content schedules.
+ ///
+ /// The content keys.
+ /// A dictionary with nodeId and an IEnumerable of matching ContentSchedules.
+ IDictionary> GetContentSchedulesByIds(Guid[] keys);
+
+ #endregion
+
+ #region Path Checks
+
+ ///
+ /// Gets a value indicating whether a document is path-publishable.
+ ///
+ /// The content to check.
+ /// True if all ancestors are published.
+ /// A document is path-publishable when all its ancestors are published.
+ bool IsPathPublishable(IContent content);
+
+ ///
+ /// Gets a value indicating whether a document is path-published.
+ ///
+ /// The content to check.
+ /// True if all ancestors and the document itself are published.
+ /// A document is path-published when all its ancestors, and the document itself, are published.
+ bool IsPathPublished(IContent? content);
+
+ #endregion
+
+ #region Workflow
+
+ ///
+ /// Saves a document and raises the "sent to publication" events.
+ ///
+ /// The content to send to publication.
+ /// The identifier of the user issuing the send to publication.
+ /// True if sending publication was successful otherwise false.
+ ///
+ /// Fires ContentSendingToPublishNotification (cancellable) before and ContentSentToPublishNotification after.
+ ///
+ bool SendToPublication(IContent? content, int userId = Constants.Security.SuperUserId);
+
+ #endregion
+
+ #region Published Content Queries
+
+ ///
+ /// Gets published children of a parent content item.
+ ///
+ /// Id of the parent to retrieve children from.
+ /// Published child content items, ordered by sort order.
+ IEnumerable GetPublishedChildren(int id);
+
+ #endregion
+}