This is an automated email from the ASF dual-hosted git repository.

He-Pin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko.git


The following commit(s) were added to refs/heads/main by this push:
     new 2214215b7b Mark public sealed traits and abstract classes with 
@DoNotInherit (#3386)
2214215b7b is described below

commit 2214215b7b44c631de4e4031f04be6be165f1d8f
Author: He-Pin(kerr) <[email protected]>
AuthorDate: Sun Jul 26 23:55:24 2026 +0800

    Mark public sealed traits and abstract classes with @DoNotInherit (#3386)
    
    * feat: mark public sealed traits and abstract classes with @DoNotInherit
    
    Motivation:
    Java users can extend sealed traits and sealed abstract classes since
    Java has no sealed keyword. These types are designed under a closed-world
    assumption and should not be extended by user code.
    
    Modification:
    Add @DoNotInherit annotation to ~110 public sealed types across actor,
    actor-typed, stream, cluster, cluster-tools, cluster-sharding,
    cluster-sharding-typed, cluster-metrics, cluster-typed, distributed-data,
    persistence, persistence-typed, persistence-tck, persistence-testkit,
    testkit, and stream-testkit modules.
    
    Result:
    Java users are clearly signaled that these types are not for extension,
    and MiMa can safely allow adding methods to these interfaces in future
    releases without breaking binary compatibility.
    
    Tests:
    - sbt actor/compile actor-typed/compile stream/compile cluster/compile
    - sbt cluster-tools/compile cluster-sharding/compile 
cluster-sharding-typed/compile
    - sbt cluster-metrics/compile distributed-data/compile cluster-typed/compile
    - sbt persistence/compile persistence-typed/compile testkit/compile
    - sbt stream-testkit/compile persistence-testkit/compile 
persistence-tck/compile
    - sbt actor/mimaReportBinaryIssues stream/mimaReportBinaryIssues 
cluster/mimaReportBinaryIssues
    - All compilation and MiMa checks pass
    
    References:
    Fixes #1270
    
    * fix: adversarial review corrections for @DoNotInherit annotations
    
    Motivation:
    Adversarial review found over-additions and missed types.
    
    Modification:
    - Remove @DoNotInherit from CapabilityFlags (root of TCK extension
      hierarchy, sub-traits are non-sealed and user-facing)
    - Add missed @DoNotInherit to: Dns.Command, LineNumbers.Result,
      Effect.ReceiveTimeoutCancelled, Effect.NoEffects,
      Effect.TimerScheduled.TimerMode, FishingOutcome.ContinueOutcome,
      Attributes.CancellationStrategy.Strategy,
      ConnectionSnapshot.ConnectionState
    
    Result:
    Annotations are now precisely scoped to types truly designed under
    closed-world assumption where users should not extend them.
    
    Tests:
    - sbt actor/compile actor-testkit-typed/compile stream/compile 
persistence-tck/compile — success
    
    References:
    Refs #1270
---
 .../apache/pekko/actor/testkit/typed/Effect.scala  |  9 +++--
 .../pekko/actor/testkit/typed/FishingOutcome.scala |  3 +-
 .../pekko/actor/typed/MessageAndSignals.scala      |  6 ++--
 .../actor/typed/delivery/ConsumerController.scala  |  3 +-
 .../actor/typed/delivery/ProducerController.scala  |  4 ++-
 .../delivery/WorkPullingProducerController.scala   |  4 ++-
 .../src/main/scala/org/apache/pekko/NotUsed.scala  |  7 +++-
 .../main/scala/org/apache/pekko/actor/Actor.scala  |  6 ++--
 .../scala/org/apache/pekko/actor/ActorPath.scala   |  5 ++-
 .../main/scala/org/apache/pekko/actor/FSM.scala    |  6 ++--
 .../org/apache/pekko/actor/FaultHandling.scala     |  6 ++--
 .../scala/org/apache/pekko/event/Logging.scala     |  4 ++-
 actor/src/main/scala/org/apache/pekko/io/Dns.scala |  4 ++-
 actor/src/main/scala/org/apache/pekko/io/Tcp.scala | 30 ++++++++++++-----
 actor/src/main/scala/org/apache/pekko/io/Udp.scala | 13 ++++++--
 .../scala/org/apache/pekko/io/UdpConnected.scala   | 13 ++++++--
 .../org/apache/pekko/io/dns/CachePolicy.scala      |  5 +--
 .../org/apache/pekko/io/dns/DnsProtocol.scala      |  4 ++-
 .../main/scala/org/apache/pekko/japi/JavaAPI.scala |  5 ++-
 .../scala/org/apache/pekko/routing/Listeners.scala |  4 ++-
 .../scala/org/apache/pekko/util/ByteString.scala   |  9 +++--
 .../scala/org/apache/pekko/util/LineNumbers.scala  |  5 ++-
 .../cluster/metrics/ClusterMetricsCollector.scala  |  5 ++-
 .../sharding/typed/ClusterShardingQuery.scala      |  5 ++-
 .../sharding/typed/ClusterShardingSettings.scala   | 17 ++++++----
 .../delivery/ShardingProducerController.scala      |  5 +--
 .../cluster/sharding/ClusterShardingSettings.scala | 11 ++++---
 .../pekko/cluster/sharding/ShardRegion.scala       |  8 +++--
 .../pekko/cluster/client/ClusterClient.scala       | 31 +++++++++++++-----
 .../cluster/pubsub/DistributedPubSubMediator.scala |  6 ++--
 .../singleton/ClusterSingletonManager.scala        |  4 ++-
 .../cluster/ddata/typed/javadsl/Replicator.scala   | 13 +++++---
 .../org/apache/pekko/cluster/ClusterEvent.scala    | 17 +++++++---
 .../scala/org/apache/pekko/cluster/Member.scala    |  6 ++--
 .../org/apache/pekko/cluster/ddata/ORMap.scala     |  5 ++-
 .../org/apache/pekko/cluster/ddata/ORSet.scala     |  5 ++-
 .../apache/pekko/cluster/ddata/Replicator.scala    | 28 +++++++++++-----
 .../apache/pekko/cluster/ddata/VersionVector.scala |  9 +++--
 .../apache/pekko/persistence/CapabilityFlags.scala |  6 +++-
 .../persistence/testkit/ProcessingPolicy.scala     |  8 +++--
 .../scaladsl/PersistenceProbeBehavior.scala        |  3 +-
 .../pekko/persistence/typed/EventAdapter.scala     |  4 ++-
 .../pekko/persistence/typed/crdt/ORSet.scala       |  4 ++-
 .../apache/pekko/persistence/PersistentActor.scala |  5 ++-
 .../pekko/persistence/journal/EventAdapter.scala   |  9 +++--
 .../pekko/stream/testkit/TestGraphStage.scala      |  5 ++-
 .../apache/pekko/stream/ActorMaterializer.scala    |  4 ++-
 .../scala/org/apache/pekko/stream/Attributes.scala |  3 +-
 .../scala/org/apache/pekko/stream/FanInShape.scala |  6 +++-
 .../org/apache/pekko/stream/FanOutShape.scala      |  6 +++-
 .../org/apache/pekko/stream/FlowMonitor.scala      |  5 ++-
 .../main/scala/org/apache/pekko/stream/Shape.scala | 10 ++++--
 .../org/apache/pekko/stream/SslTlsOptions.scala    | 38 +++++++++++++++-------
 .../org/apache/pekko/stream/Supervision.scala      |  5 ++-
 .../org/apache/pekko/stream/ThrottleMode.scala     |  5 ++-
 .../org/apache/pekko/stream/scaladsl/Graph.scala   |  7 ++--
 .../org/apache/pekko/stream/scaladsl/Hub.scala     |  3 +-
 .../pekko/stream/snapshot/MaterializerState.scala  |  4 ++-
 .../org/apache/pekko/testkit/SocketUtil.scala      |  6 +++-
 .../apache/pekko/testkit/TestEventListener.scala   |  5 ++-
 60 files changed, 350 insertions(+), 131 deletions(-)

diff --git 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/Effect.scala
 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/Effect.scala
index 350639e4c8..0027780d51 100644
--- 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/Effect.scala
+++ 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/Effect.scala
@@ -258,7 +258,8 @@ object Effect {
 
   case object ReceiveTimeoutCancelled extends ReceiveTimeoutCancelled
 
-  sealed abstract class ReceiveTimeoutCancelled extends Effect
+  /** Not for user extension */
+  @DoNotInherit sealed abstract class ReceiveTimeoutCancelled extends Effect
 
   /**
    * The behavior used `context.scheduleOnce` to schedule `message` to be sent 
to `target` after `delay`
@@ -281,7 +282,8 @@ object Effect {
   object TimerScheduled {
     import scala.jdk.DurationConverters._
 
-    sealed trait TimerMode
+    /** Not for user extension */
+    @DoNotInherit sealed trait TimerMode
     case object FixedRateMode extends TimerMode
     case class FixedRateModeWithInitialDelay(initialDelay: FiniteDuration) 
extends TimerMode
     case object FixedDelayMode extends TimerMode
@@ -308,6 +310,7 @@ object Effect {
 
   /**
    * Used for NoEffects expectations by type
+   * Not for user extension
    */
-  sealed abstract class NoEffects extends Effect
+  @DoNotInherit sealed abstract class NoEffects extends Effect
 }
diff --git 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/FishingOutcome.scala
 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/FishingOutcome.scala
index 1fff22037f..842e9a9605 100644
--- 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/FishingOutcome.scala
+++ 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/FishingOutcome.scala
@@ -26,7 +26,8 @@ import pekko.annotation.DoNotInherit
 
 object FishingOutcome {
 
-  sealed trait ContinueOutcome extends FishingOutcome
+  /** Not for user extension */
+  @DoNotInherit sealed trait ContinueOutcome extends FishingOutcome
   case object Continue extends ContinueOutcome
   case object ContinueAndIgnore extends ContinueOutcome
   case object Complete extends FishingOutcome
diff --git 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/MessageAndSignals.scala
 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/MessageAndSignals.scala
index efcd06ef95..975dd4a0e1 100644
--- 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/MessageAndSignals.scala
+++ 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/MessageAndSignals.scala
@@ -38,8 +38,9 @@ trait Signal
  * Lifecycle signal that is fired upon restart of the Actor before replacing
  * the behavior with the fresh one (i.e. this signal is received within the
  * behavior that failed).
+ * Not for user extension
  */
-sealed abstract class PreRestart extends Signal
+@DoNotInherit sealed abstract class PreRestart extends Signal
 case object PreRestart extends PreRestart {
   def instance: PreRestart = this
 }
@@ -48,8 +49,9 @@ case object PreRestart extends PreRestart {
  * Lifecycle signal that is fired after this actor and all its child actors
  * (transitively) have terminated. The [[Terminated]] signal is only sent to
  * registered watchers after this signal has been processed.
+ * Not for user extension
  */
-sealed abstract class PostStop extends Signal
+@DoNotInherit sealed abstract class PostStop extends Signal
 // comment copied onto object for better hints in IDEs
 /**
  * Lifecycle signal that is fired after this actor and all its child actors
diff --git 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/ConsumerController.scala
 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/ConsumerController.scala
index 72ae6b08ff..9aeb3e0fe7 100644
--- 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/ConsumerController.scala
+++ 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/ConsumerController.scala
@@ -62,7 +62,8 @@ object ConsumerController {
 
   type SeqNr = Long
 
-  sealed trait Command[+A] extends UnsealedInternalCommand
+  /** Not for user extension */
+  @DoNotInherit sealed trait Command[+A] extends UnsealedInternalCommand
 
   /**
    * Initial message from the consumer actor. The `deliverTo` is typically 
constructed
diff --git 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/ProducerController.scala
 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/ProducerController.scala
index 7d4368642e..d85458b711 100644
--- 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/ProducerController.scala
+++ 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/ProducerController.scala
@@ -29,6 +29,7 @@ import 
pekko.actor.typed.delivery.internal.DeliverySerializable
 import pekko.actor.typed.delivery.internal.ProducerControllerImpl
 import pekko.actor.typed.scaladsl.Behaviors
 import pekko.annotation.ApiMayChange
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.util.Helpers.Requiring
 import pekko.util.Helpers.toRootLowerCase
@@ -99,7 +100,8 @@ object ProducerController {
 
   type SeqNr = Long
 
-  sealed trait Command[A] extends UnsealedInternalCommand
+  /** Not for user extension */
+  @DoNotInherit sealed trait Command[A] extends UnsealedInternalCommand
 
   /**
    * Initial message from the producer actor. The `producer` is typically 
constructed
diff --git 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/WorkPullingProducerController.scala
 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/WorkPullingProducerController.scala
index b3a63a5858..78cf5fd4e0 100644
--- 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/WorkPullingProducerController.scala
+++ 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/delivery/WorkPullingProducerController.scala
@@ -29,6 +29,7 @@ import 
pekko.actor.typed.delivery.internal.WorkPullingProducerControllerImpl
 import pekko.actor.typed.receptionist.ServiceKey
 import pekko.actor.typed.scaladsl.Behaviors
 import pekko.annotation.ApiMayChange
+import pekko.annotation.DoNotInherit
 
 import com.typesafe.config.Config
 
@@ -111,7 +112,8 @@ object WorkPullingProducerController {
 
   import WorkPullingProducerControllerImpl.UnsealedInternalCommand
 
-  sealed trait Command[A] extends UnsealedInternalCommand
+  /** Not for user extension */
+  @DoNotInherit sealed trait Command[A] extends UnsealedInternalCommand
 
   /**
    * Initial message from the producer actor. The `producer` is typically 
constructed
diff --git a/actor/src/main/scala/org/apache/pekko/NotUsed.scala 
b/actor/src/main/scala/org/apache/pekko/NotUsed.scala
index c010fcd284..2619764c4f 100644
--- a/actor/src/main/scala/org/apache/pekko/NotUsed.scala
+++ b/actor/src/main/scala/org/apache/pekko/NotUsed.scala
@@ -13,13 +13,18 @@
 
 package org.apache.pekko
 
+import org.apache.pekko
+import pekko.annotation.DoNotInherit
+
 /**
  * This type is used in generic type signatures wherever the actual value is 
of no importance.
  * It is a combination of Scala’s `Unit` and Java’s `Void`, which both have 
different issues when
  * used from the other language. An example use-case is the materialized value 
of a Pekko Stream for cases
  * where no result shall be returned from materialization.
+ *
+ * Not for user extension
  */
-sealed abstract class NotUsed
+@DoNotInherit sealed abstract class NotUsed
 
 case object NotUsed extends NotUsed {
 
diff --git a/actor/src/main/scala/org/apache/pekko/actor/Actor.scala 
b/actor/src/main/scala/org/apache/pekko/actor/Actor.scala
index 404c7e40e0..3ba8abafc0 100644
--- a/actor/src/main/scala/org/apache/pekko/actor/Actor.scala
+++ b/actor/src/main/scala/org/apache/pekko/actor/Actor.scala
@@ -22,7 +22,7 @@ import scala.util.control.NoStackTrace
 
 import org.apache.pekko
 import pekko.PekkoException
-import pekko.annotation.InternalApi
+import pekko.annotation.{ DoNotInherit, InternalApi }
 import pekko.event.LoggingAdapter
 
 /**
@@ -310,7 +310,9 @@ final case class UnhandledMessage(
  * Used for internal ACKing protocol. But exposed as utility class for 
user-specific ACKing protocols as well.
  */
 object Status {
-  sealed trait Status extends Serializable
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait Status extends Serializable
 
   /**
    * This class/message type is preferably used to indicate success of some 
operation performed.
diff --git a/actor/src/main/scala/org/apache/pekko/actor/ActorPath.scala 
b/actor/src/main/scala/org/apache/pekko/actor/ActorPath.scala
index d52602cc83..ef43038b54 100644
--- a/actor/src/main/scala/org/apache/pekko/actor/ActorPath.scala
+++ b/actor/src/main/scala/org/apache/pekko/actor/ActorPath.scala
@@ -21,6 +21,7 @@ import scala.collection.immutable
 import scala.jdk.CollectionConverters._
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 
 /**
  * Java API
@@ -170,10 +171,12 @@ object ActorPath {
  * re-created with the same path. In other words, in contrast to how actor
  * references are compared the unique id of the actor is not taken into account
  * when comparing actor paths.
+ *
+ * Not for user extension
  */
 @nowarn("msg=@SerialVersionUID (has no effect|does nothing)")
 @SerialVersionUID(1L)
-sealed trait ActorPath extends Comparable[ActorPath] with Serializable {
+@DoNotInherit sealed trait ActorPath extends Comparable[ActorPath] with 
Serializable {
 
   /**
    * The Address under which this path can be reached; walks up the tree to
diff --git a/actor/src/main/scala/org/apache/pekko/actor/FSM.scala 
b/actor/src/main/scala/org/apache/pekko/actor/FSM.scala
index 8f3fe318b6..aadedbc0d9 100644
--- a/actor/src/main/scala/org/apache/pekko/actor/FSM.scala
+++ b/actor/src/main/scala/org/apache/pekko/actor/FSM.scala
@@ -23,7 +23,7 @@ import scala.concurrent.duration.FiniteDuration
 import language.implicitConversions
 
 import org.apache.pekko
-import pekko.annotation.InternalApi
+import pekko.annotation.{ DoNotInherit, InternalApi }
 import pekko.routing.{ Deafen, Listen, Listeners }
 
 object FSM {
@@ -69,8 +69,10 @@ object FSM {
 
   /**
    * Reason why this [[pekko.actor.FSM]] is shutting down.
+   *
+   * Not for user extension
    */
-  sealed trait Reason
+  @DoNotInherit sealed trait Reason
 
   /**
    * Default reason if calling `stop()`.
diff --git a/actor/src/main/scala/org/apache/pekko/actor/FaultHandling.scala 
b/actor/src/main/scala/org/apache/pekko/actor/FaultHandling.scala
index 73b97fb7f6..566a8e4331 100644
--- a/actor/src/main/scala/org/apache/pekko/actor/FaultHandling.scala
+++ b/actor/src/main/scala/org/apache/pekko/actor/FaultHandling.scala
@@ -25,7 +25,7 @@ import scala.language.implicitConversions
 import scala.util.control.NonFatal
 
 import org.apache.pekko
-import pekko.annotation.InternalApi
+import pekko.annotation.{ DoNotInherit, InternalApi }
 import pekko.event.Logging
 import pekko.event.Logging.{ Error, LogEvent, LogLevel }
 import pekko.japi.Util.immutableSeq
@@ -113,7 +113,9 @@ trait SupervisorStrategyLowPriorityImplicits { this: 
SupervisorStrategy.type =>
 }
 
 object SupervisorStrategy extends SupervisorStrategyLowPriorityImplicits {
-  sealed trait Directive {
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait Directive {
 
     /** INTERNAL API */
     @InternalApi
diff --git a/actor/src/main/scala/org/apache/pekko/event/Logging.scala 
b/actor/src/main/scala/org/apache/pekko/event/Logging.scala
index 3877e89f1e..db2a212241 100644
--- a/actor/src/main/scala/org/apache/pekko/event/Logging.scala
+++ b/actor/src/main/scala/org/apache/pekko/event/Logging.scala
@@ -731,8 +731,10 @@ object Logging {
 
   /**
    * Base type of LogEvents
+   *
+   * Not for user extension
    */
-  sealed trait LogEvent extends NoSerializationVerificationNeeded {
+  @DoNotInherit sealed trait LogEvent extends 
NoSerializationVerificationNeeded {
 
     /**
      * The thread that created this log event
diff --git a/actor/src/main/scala/org/apache/pekko/io/Dns.scala 
b/actor/src/main/scala/org/apache/pekko/io/Dns.scala
index b0a9a14a36..9fa581ce25 100644
--- a/actor/src/main/scala/org/apache/pekko/io/Dns.scala
+++ b/actor/src/main/scala/org/apache/pekko/io/Dns.scala
@@ -46,7 +46,9 @@ abstract class Dns {
 }
 
 object Dns extends ExtensionId[DnsExt] with ExtensionIdProvider {
-  sealed trait Command
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait Command
 
   /**
    * Lookup if a DNS resolved is cached. The exact behavior of caching will 
depend on
diff --git a/actor/src/main/scala/org/apache/pekko/io/Tcp.scala 
b/actor/src/main/scala/org/apache/pekko/io/Tcp.scala
index 97641f90ce..77ea5a2ad2 100644
--- a/actor/src/main/scala/org/apache/pekko/io/Tcp.scala
+++ b/actor/src/main/scala/org/apache/pekko/io/Tcp.scala
@@ -26,7 +26,7 @@ import scala.jdk.DurationConverters._
 
 import org.apache.pekko
 import pekko.actor._
-import pekko.annotation.InternalApi
+import pekko.annotation.{ DoNotInherit, InternalApi }
 import pekko.io.Inet._
 import pekko.util.{ ByteString, Helpers }
 import pekko.util.Helpers.Requiring
@@ -107,8 +107,10 @@ object Tcp extends ExtensionId[TcpExt] with 
ExtensionIdProvider {
 
   /**
    * The common interface for [[Command]] and [[Event]].
+   *
+   * Not for user extension
    */
-  sealed trait Message extends NoSerializationVerificationNeeded
+  @DoNotInherit sealed trait Message extends NoSerializationVerificationNeeded
 
   /// COMMANDS
 
@@ -196,8 +198,10 @@ object Tcp extends ExtensionId[TcpExt] with 
ExtensionIdProvider {
 
   /**
    * Common interface for all commands which aim to close down an open 
connection.
+   *
+   * Not for user extension
    */
-  sealed trait CloseCommand extends Command with DeadLetterSuppression {
+  @DoNotInherit sealed trait CloseCommand extends Command with 
DeadLetterSuppression {
 
     /**
      * The corresponding event which is sent as an acknowledgment once the
@@ -268,8 +272,10 @@ object Tcp extends ExtensionId[TcpExt] with 
ExtensionIdProvider {
 
   /**
    * Common interface for all write commands.
+   *
+   * Not for user extension
    */
-  sealed abstract class WriteCommand extends Command {
+  @DoNotInherit sealed abstract class WriteCommand extends Command {
 
     /**
      * Prepends this command with another `Write` or `WriteFile` to form
@@ -317,8 +323,10 @@ object Tcp extends ExtensionId[TcpExt] with 
ExtensionIdProvider {
 
   /**
    * Common supertype of [[Write]] and [[WritePath]].
+   *
+   * Not for user extension
    */
-  sealed abstract class SimpleWriteCommand extends WriteCommand {
+  @DoNotInherit sealed abstract class SimpleWriteCommand extends WriteCommand {
     require(ack != null, "ack must be non-null. Use NoAck if you don't want 
acks.")
 
     /**
@@ -504,8 +512,10 @@ object Tcp extends ExtensionId[TcpExt] with 
ExtensionIdProvider {
    * which it is safe to send at least one write. This means that all writes 
preceding
    * the first [[CommandFailed]] message have been enqueued to the O/S kernel 
at this
    * point.
+   *
+   * Not for user extension
    */
-  sealed trait WritingResumed extends Event
+  @DoNotInherit sealed trait WritingResumed extends Event
   case object WritingResumed extends WritingResumed
 
   /**
@@ -518,15 +528,19 @@ object Tcp extends ExtensionId[TcpExt] with 
ExtensionIdProvider {
   /**
    * The sender of an `Unbind` command will receive confirmation through this
    * message once the listening socket has been closed.
+   *
+   * Not for user extension
    */
-  sealed trait Unbound extends Event
+  @DoNotInherit sealed trait Unbound extends Event
   case object Unbound extends Unbound
 
   /**
    * This is the common interface for all events which indicate that a 
connection
    * has been closed or half-closed.
+   *
+   * Not for user extension
    */
-  sealed trait ConnectionClosed extends Event with DeadLetterSuppression {
+  @DoNotInherit sealed trait ConnectionClosed extends Event with 
DeadLetterSuppression {
 
     /**
      * `true` iff the connection has been closed in response to an `Abort` 
command.
diff --git a/actor/src/main/scala/org/apache/pekko/io/Udp.scala 
b/actor/src/main/scala/org/apache/pekko/io/Udp.scala
index 995f463f4f..d54d4fe505 100644
--- a/actor/src/main/scala/org/apache/pekko/io/Udp.scala
+++ b/actor/src/main/scala/org/apache/pekko/io/Udp.scala
@@ -21,6 +21,7 @@ import scala.collection.immutable
 
 import org.apache.pekko
 import pekko.actor._
+import pekko.annotation.DoNotInherit
 import pekko.io.Inet.{ SoJavaFactories, SocketOption }
 import pekko.util.ByteString
 import pekko.util.Helpers.Requiring
@@ -53,8 +54,10 @@ object Udp extends ExtensionId[UdpExt] with 
ExtensionIdProvider {
 
   /**
    * The common interface for [[Command]] and [[Event]].
+   *
+   * Not for user extension
    */
-  sealed trait Message
+  @DoNotInherit sealed trait Message
 
   /**
    * The common type of all commands supported by the UDP implementation.
@@ -176,15 +179,19 @@ object Udp extends ExtensionId[UdpExt] with 
ExtensionIdProvider {
 
   /**
    * The “simple sender” sends this message type in response to a 
[[SimpleSender]] query.
+   *
+   * Not for user extension
    */
-  sealed trait SimpleSenderReady extends Event
+  @DoNotInherit sealed trait SimpleSenderReady extends Event
   case object SimpleSenderReady extends SimpleSenderReady
 
   /**
    * This message is sent by the listener actor in response to an `Unbind` 
command
    * after the socket has been closed.
+   *
+   * Not for user extension
    */
-  sealed trait Unbound
+  @DoNotInherit sealed trait Unbound
   case object Unbound extends Unbound
 
   /**
diff --git a/actor/src/main/scala/org/apache/pekko/io/UdpConnected.scala 
b/actor/src/main/scala/org/apache/pekko/io/UdpConnected.scala
index cb670dbc38..acf31e173c 100644
--- a/actor/src/main/scala/org/apache/pekko/io/UdpConnected.scala
+++ b/actor/src/main/scala/org/apache/pekko/io/UdpConnected.scala
@@ -21,6 +21,7 @@ import scala.collection.immutable
 
 import org.apache.pekko
 import pekko.actor._
+import pekko.annotation.DoNotInherit
 import pekko.io.Inet.SocketOption
 import pekko.io.Udp.UdpSettings
 import pekko.util.ByteString
@@ -51,8 +52,10 @@ object UdpConnected extends ExtensionId[UdpConnectedExt] 
with ExtensionIdProvide
 
   /**
    * The common interface for [[Command]] and [[Event]].
+   *
+   * Not for user extension
    */
-  sealed trait Message
+  @DoNotInherit sealed trait Message
 
   /**
    * The common type of all commands supported by the UDP implementation.
@@ -151,15 +154,19 @@ object UdpConnected extends ExtensionId[UdpConnectedExt] 
with ExtensionIdProvide
    * This message is sent by the connection actor to the actor which sent the
    * [[Connect]] message when the UDP socket has been bound to the local and
    * remote addresses given.
+   *
+   * Not for user extension
    */
-  sealed trait Connected extends Event
+  @DoNotInherit sealed trait Connected extends Event
   case object Connected extends Connected
 
   /**
    * This message is sent by the connection actor to the actor which sent the
    * `Disconnect` message when the UDP socket has been closed.
+   *
+   * Not for user extension
    */
-  sealed trait Disconnected extends Event
+  @DoNotInherit sealed trait Disconnected extends Event
   case object Disconnected extends Disconnected
 
 }
diff --git a/actor/src/main/scala/org/apache/pekko/io/dns/CachePolicy.scala 
b/actor/src/main/scala/org/apache/pekko/io/dns/CachePolicy.scala
index 803192fe2d..5b71336470 100644
--- a/actor/src/main/scala/org/apache/pekko/io/dns/CachePolicy.scala
+++ b/actor/src/main/scala/org/apache/pekko/io/dns/CachePolicy.scala
@@ -17,11 +17,12 @@ import scala.concurrent.duration.{ Duration, 
FiniteDuration, _ }
 import scala.jdk.DurationConverters._
 
 import org.apache.pekko
-import pekko.annotation.InternalApi
+import pekko.annotation.{ DoNotInherit, InternalApi }
 
 object CachePolicy {
 
-  sealed trait CachePolicy
+  /** Not for user extension */
+  @DoNotInherit sealed trait CachePolicy
   case object Never extends CachePolicy
   case object Forever extends CachePolicy
 
diff --git a/actor/src/main/scala/org/apache/pekko/io/dns/DnsProtocol.scala 
b/actor/src/main/scala/org/apache/pekko/io/dns/DnsProtocol.scala
index 665665ebbb..28a4517451 100644
--- a/actor/src/main/scala/org/apache/pekko/io/dns/DnsProtocol.scala
+++ b/actor/src/main/scala/org/apache/pekko/io/dns/DnsProtocol.scala
@@ -24,6 +24,7 @@ import scala.jdk.CollectionConverters._
 
 import org.apache.pekko
 import pekko.actor.NoSerializationVerificationNeeded
+import pekko.annotation.DoNotInherit
 import pekko.io.IpVersionSelector
 import pekko.routing.ConsistentHashingRouter.ConsistentHashable
 
@@ -37,7 +38,8 @@ import 
pekko.routing.ConsistentHashingRouter.ConsistentHashable
  */
 object DnsProtocol {
 
-  sealed trait RequestType
+  /** Not for user extension */
+  @DoNotInherit sealed trait RequestType
   final case class Ip(ipv4: Boolean = true, ipv6: Boolean = true) extends 
RequestType
   case object Srv extends RequestType
 
diff --git a/actor/src/main/scala/org/apache/pekko/japi/JavaAPI.scala 
b/actor/src/main/scala/org/apache/pekko/japi/JavaAPI.scala
index d89ac697b4..b2c173ed8e 100644
--- a/actor/src/main/scala/org/apache/pekko/japi/JavaAPI.scala
+++ b/actor/src/main/scala/org/apache/pekko/japi/JavaAPI.scala
@@ -19,6 +19,7 @@ import scala.runtime.AbstractPartialFunction
 import scala.util.control.NoStackTrace
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.util.Collections.EmptyImmutableSeq
 
 /**
@@ -36,7 +37,9 @@ object Pair {
 }
 
 object JavaPartialFunction {
-  sealed abstract class NoMatchException extends RuntimeException with 
NoStackTrace
+
+  /** Not for user extension */
+  @DoNotInherit sealed abstract class NoMatchException extends 
RuntimeException with NoStackTrace
   case object NoMatch extends NoMatchException
   final def noMatch(): RuntimeException = NoMatch
 }
diff --git a/actor/src/main/scala/org/apache/pekko/routing/Listeners.scala 
b/actor/src/main/scala/org/apache/pekko/routing/Listeners.scala
index 792e6b60db..ef5972011a 100644
--- a/actor/src/main/scala/org/apache/pekko/routing/Listeners.scala
+++ b/actor/src/main/scala/org/apache/pekko/routing/Listeners.scala
@@ -17,8 +17,10 @@ import java.util.{ Set, TreeSet }
 
 import org.apache.pekko
 import pekko.actor.{ Actor, ActorRef }
+import pekko.annotation.DoNotInherit
 
-sealed trait ListenerMessage
+/** Not for user extension */
+@DoNotInherit sealed trait ListenerMessage
 final case class Listen(listener: ActorRef) extends ListenerMessage
 final case class Deafen(listener: ActorRef) extends ListenerMessage
 final case class WithListeners(f: (ActorRef) => Unit) extends ListenerMessage
diff --git a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala 
b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
index ac60ca92e6..16b02a49c2 100644
--- a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
+++ b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
@@ -27,6 +27,7 @@ import scala.jdk.CollectionConverters._
 import scala.reflect.ClassTag
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.io.UnsynchronizedByteArrayInputStream
 
 object ByteString {
@@ -1867,8 +1868,10 @@ object ByteString {
  * and also providing a thread safe way of working with bytes.
  *
  * TODO: Add performance characteristics
+ *
+ * Not for user extension
  */
-sealed abstract class ByteString
+@DoNotInherit sealed abstract class ByteString
     extends IndexedSeq[Byte]
     with IndexedSeqOps[Byte, IndexedSeq, ByteString]
     with StrictOptimizedSeqOps[Byte, IndexedSeq, ByteString] {
@@ -2742,8 +2745,10 @@ object CompactByteString {
  *
  * The ByteString is guaranteed to be contiguous in memory and to use only
  * as much memory as required for its contents.
+ *
+ * Not for user extension
  */
-sealed abstract class CompactByteString extends ByteString with Serializable {
+@DoNotInherit sealed abstract class CompactByteString extends ByteString with 
Serializable {
   def isCompact: Boolean = true
   def compact: this.type = this
 }
diff --git a/actor/src/main/scala/org/apache/pekko/util/LineNumbers.scala 
b/actor/src/main/scala/org/apache/pekko/util/LineNumbers.scala
index b70c7ca0f1..6c82e79f2c 100644
--- a/actor/src/main/scala/org/apache/pekko/util/LineNumbers.scala
+++ b/actor/src/main/scala/org/apache/pekko/util/LineNumbers.scala
@@ -19,6 +19,8 @@ import java.lang.invoke.{ MethodHandle, MethodHandles, 
MethodType, SerializedLam
 import scala.annotation.switch
 import scala.util.control.NonFatal
 
+import org.apache.pekko.annotation.DoNotInherit
+
 /**
  * This is a minimized byte-code parser that concentrates exclusively on line
  * numbers and source file extraction. It works for all normal classes up to
@@ -39,7 +41,8 @@ object LineNumbers {
         .findVirtual(clazz, "writeReplace", writeReplaceMethodType)
   }
 
-  sealed trait Result
+  /** Not for user extension */
+  @DoNotInherit sealed trait Result
   case object NoSourceInfo extends Result
   final case class UnknownSourceFormat(explanation: String) extends Result
   final case class SourceFile(filename: String) extends Result {
diff --git 
a/cluster-metrics/src/main/scala/org/apache/pekko/cluster/metrics/ClusterMetricsCollector.scala
 
b/cluster-metrics/src/main/scala/org/apache/pekko/cluster/metrics/ClusterMetricsCollector.scala
index bcb473101b..a5deda84b3 100644
--- 
a/cluster-metrics/src/main/scala/org/apache/pekko/cluster/metrics/ClusterMetricsCollector.scala
+++ 
b/cluster-metrics/src/main/scala/org/apache/pekko/cluster/metrics/ClusterMetricsCollector.scala
@@ -24,6 +24,7 @@ import pekko.actor.ActorLogging
 import pekko.actor.Address
 import pekko.actor.DeadLetterSuppression
 import pekko.actor.Props
+import pekko.annotation.DoNotInherit
 import pekko.cluster.Cluster
 import pekko.cluster.ClusterEvent
 import pekko.cluster.Member
@@ -31,8 +32,10 @@ import pekko.cluster.MemberStatus
 
 /**
  *  Runtime collection management commands.
+ *
+ *  Not for user extension
  */
-sealed abstract class CollectionControlMessage extends Serializable
+@DoNotInherit sealed abstract class CollectionControlMessage extends 
Serializable
 
 /**
  * Command for `ClusterMetricsSupervisor` to start metrics collection.
diff --git 
a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/ClusterShardingQuery.scala
 
b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/ClusterShardingQuery.scala
index 308c9566fb..0507e8b989 100644
--- 
a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/ClusterShardingQuery.scala
+++ 
b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/ClusterShardingQuery.scala
@@ -18,14 +18,17 @@ import scala.jdk.DurationConverters._
 
 import org.apache.pekko
 import pekko.actor.typed.ActorRef
+import pekko.annotation.DoNotInherit
 import pekko.cluster.sharding.ShardRegion.ClusterShardingStats
 import pekko.cluster.sharding.ShardRegion.CurrentShardRegionState
 import pekko.cluster.sharding.typed.scaladsl.EntityTypeKey
 
 /**
  * Protocol for querying sharding state e.g. A ShardRegion's state
+ *
+ * Not for user extension
  */
-sealed trait ClusterShardingQuery
+@DoNotInherit sealed trait ClusterShardingQuery
 
 /**
  * Query the ShardRegion state for the given entity type key. This will get 
the state of the
diff --git 
a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/ClusterShardingSettings.scala
 
b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/ClusterShardingSettings.scala
index f4a5cf6c98..a8a56035e3 100644
--- 
a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/ClusterShardingSettings.scala
+++ 
b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/ClusterShardingSettings.scala
@@ -19,7 +19,7 @@ import scala.jdk.DurationConverters._
 
 import org.apache.pekko
 import pekko.actor.typed.ActorSystem
-import pekko.annotation.InternalApi
+import pekko.annotation.{ DoNotInherit, InternalApi }
 import pekko.cluster.ClusterSettings.DataCenter
 import pekko.cluster.sharding.{ ClusterShardingSettings => 
ClassicShardingSettings }
 import pekko.cluster.singleton.{ ClusterSingletonManagerSettings => 
ClassicClusterSingletonManagerSettings }
@@ -122,7 +122,8 @@ object ClusterShardingSettings {
   private def option(role: String): Option[String] =
     if (role == "" || (role eq null)) None else Option(role)
 
-  sealed trait StateStoreMode { def name: String }
+  /** Not for user extension */
+  @DoNotInherit sealed trait StateStoreMode { def name: String }
 
   /**
    * Java API
@@ -158,7 +159,8 @@ object ClusterShardingSettings {
    */
   def rememberEntitiesStoreModeDdata(): RememberEntitiesStoreMode = 
RememberEntitiesStoreModeDData
 
-  sealed trait RememberEntitiesStoreMode { def name: String }
+  /** Not for user extension */
+  @DoNotInherit sealed trait RememberEntitiesStoreMode { def name: String }
 
   object RememberEntitiesStoreMode {
 
@@ -301,7 +303,8 @@ object ClusterShardingSettings {
       }
     }
 
-    sealed trait PolicySettings
+    /** Not for user extension */
+    @DoNotInherit sealed trait PolicySettings
 
     object LeastRecentlyUsedSettings {
       val defaults: LeastRecentlyUsedSettings = new 
LeastRecentlyUsedSettings(segmentedSettings = None)
@@ -409,7 +412,8 @@ object ClusterShardingSettings {
           }
       }
 
-      sealed trait FilterSettings
+      /** Not for user extension */
+      @DoNotInherit sealed trait FilterSettings
 
       object FrequencySketchSettings {
         val defaults =
@@ -530,7 +534,8 @@ object ClusterShardingSettings {
           }
       }
 
-      sealed trait OptimizerSettings
+      /** Not for user extension */
+      @DoNotInherit sealed trait OptimizerSettings
 
       object HillClimbingSettings {
         val defaults: HillClimbingSettings = new HillClimbingSettings(
diff --git 
a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/delivery/ShardingProducerController.scala
 
b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/delivery/ShardingProducerController.scala
index 4266c16011..a900e50c0f 100644
--- 
a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/delivery/ShardingProducerController.scala
+++ 
b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/delivery/ShardingProducerController.scala
@@ -29,7 +29,7 @@ import pekko.actor.typed.delivery.ConsumerController
 import pekko.actor.typed.delivery.DurableProducerQueue
 import pekko.actor.typed.delivery.ProducerController
 import pekko.actor.typed.scaladsl.Behaviors
-import pekko.annotation.ApiMayChange
+import pekko.annotation.{ ApiMayChange, DoNotInherit }
 import pekko.cluster.sharding.typed.ShardingEnvelope
 import 
pekko.cluster.sharding.typed.delivery.internal.ShardingProducerControllerImpl
 
@@ -107,7 +107,8 @@ object ShardingProducerController {
 
   type EntityId = String
 
-  sealed trait Command[A] extends UnsealedInternalCommand
+  /** Not for user extension */
+  @DoNotInherit sealed trait Command[A] extends UnsealedInternalCommand
 
   /**
    * Initial message from the producer actor. The `producer` is typically 
constructed
diff --git 
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ClusterShardingSettings.scala
 
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ClusterShardingSettings.scala
index 9093e912a6..aa06cc002e 100644
--- 
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ClusterShardingSettings.scala
+++ 
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ClusterShardingSettings.scala
@@ -20,7 +20,7 @@ import scala.jdk.DurationConverters._
 import org.apache.pekko
 import pekko.actor.ActorSystem
 import pekko.actor.NoSerializationVerificationNeeded
-import pekko.annotation.InternalApi
+import pekko.annotation.{ DoNotInherit, InternalApi }
 import pekko.cluster.Cluster
 import pekko.cluster.singleton.ClusterSingletonManagerSettings
 import pekko.coordination.lease.LeaseUsageSettings
@@ -258,7 +258,8 @@ object ClusterShardingSettings {
         }
     }
 
-    sealed trait PolicySettings
+    /** Not for user extension */
+    @DoNotInherit sealed trait PolicySettings
 
     object LeastRecentlyUsedSettings {
       val defaults: LeastRecentlyUsedSettings = new 
LeastRecentlyUsedSettings(segmentedSettings = None)
@@ -356,7 +357,8 @@ object ClusterShardingSettings {
           }
       }
 
-      sealed trait FilterSettings
+      /** Not for user extension */
+      @DoNotInherit sealed trait FilterSettings
 
       object FrequencySketchSettings {
         val defaults =
@@ -463,7 +465,8 @@ object ClusterShardingSettings {
           }
       }
 
-      sealed trait OptimizerSettings
+      /** Not for user extension */
+      @DoNotInherit sealed trait OptimizerSettings
 
       object HillClimbingSettings {
         val defaults: HillClimbingSettings = new HillClimbingSettings(
diff --git 
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ShardRegion.scala
 
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ShardRegion.scala
index b5bd7f5cc5..91a42eb540 100644
--- 
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ShardRegion.scala
+++ 
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ShardRegion.scala
@@ -27,7 +27,7 @@ import scala.util.{ Failure, Success }
 import org.apache.pekko
 import pekko.Done
 import pekko.actor._
-import pekko.annotation.{ InternalApi, InternalStableApi }
+import pekko.annotation.{ DoNotInherit, InternalApi, InternalStableApi }
 import pekko.cluster.Cluster
 import pekko.cluster.ClusterEvent._
 import pekko.cluster.ClusterSettings
@@ -194,7 +194,8 @@ object ShardRegion {
     }
   }
 
-  sealed trait ShardRegionCommand
+  /** Not for user extension */
+  @DoNotInherit sealed trait ShardRegionCommand
 
   /**
    * If the state of the entities are persistent you may stop entities that 
are not used to
@@ -235,7 +236,8 @@ object ShardRegion {
    */
   final case class ShardInitialized(shardId: ShardId)
 
-  sealed trait ShardRegionQuery
+  /** Not for user extension */
+  @DoNotInherit sealed trait ShardRegionQuery
 
   /**
    * Send this message to the `ShardRegion` actor to request for 
[[CurrentRegions]],
diff --git 
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/client/ClusterClient.scala
 
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/client/ClusterClient.scala
index 8e787a14bf..e953c151ff 100644
--- 
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/client/ClusterClient.scala
+++ 
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/client/ClusterClient.scala
@@ -42,6 +42,7 @@ import pekko.actor.NoSerializationVerificationNeeded
 import pekko.actor.Props
 import pekko.actor.ReceiveTimeout
 import pekko.actor.Terminated
+import pekko.annotation.DoNotInherit
 import pekko.cluster.Cluster
 import pekko.cluster.ClusterEvent._
 import pekko.cluster.Member
@@ -211,8 +212,10 @@ final class ClusterClientSettings(
 /**
  * Declares a super type for all events emitted by the `ClusterClient`
  * in relation to contact points being added or removed.
+ *
+ * Not for user extension
  */
-sealed trait ContactPointChange {
+@DoNotInherit sealed trait ContactPointChange {
   val contactPoint: ActorPath
 }
 
@@ -228,7 +231,8 @@ final case class ContactPointAdded(override val 
contactPoint: ActorPath) extends
  */
 final case class ContactPointRemoved(override val contactPoint: ActorPath) 
extends ContactPointChange
 
-sealed abstract class SubscribeContactPoints
+/** Not for user extension */
+@DoNotInherit sealed abstract class SubscribeContactPoints
 
 /**
  * Subscribe to a cluster client's contact point changes where
@@ -246,7 +250,8 @@ case object SubscribeContactPoints extends 
SubscribeContactPoints {
   def getInstance = this
 }
 
-sealed abstract class UnsubscribeContactPoints
+/** Not for user extension */
+@DoNotInherit sealed abstract class UnsubscribeContactPoints
 
 /**
  * Explicitly unsubscribe from contact point change events.
@@ -259,7 +264,8 @@ case object UnsubscribeContactPoints extends 
UnsubscribeContactPoints {
   def getInstance = this
 }
 
-sealed abstract class GetContactPoints
+/** Not for user extension */
+@DoNotInherit sealed abstract class GetContactPoints
 
 /**
  * Get the contact points known to this client. A ``ContactPoints`` message
@@ -787,14 +793,18 @@ final class ClusterReceptionistSettings(
 
 /**
  * Marker trait for remote messages with special serializer.
+ *
+ * Not for user extension
  */
-sealed trait ClusterClientMessage extends Serializable
+@DoNotInherit sealed trait ClusterClientMessage extends Serializable
 
 /**
  * Declares a super type for all events emitted by the `ClusterReceptionist`.
  * in relation to cluster clients being interacted with.
+ *
+ * Not for user extension
  */
-sealed trait ClusterClientInteraction {
+@DoNotInherit sealed trait ClusterClientInteraction {
   val clusterClient: ActorRef
 }
 
@@ -810,7 +820,8 @@ final case class ClusterClientUp(override val 
clusterClient: ActorRef) extends C
  */
 final case class ClusterClientUnreachable(override val clusterClient: 
ActorRef) extends ClusterClientInteraction
 
-sealed abstract class SubscribeClusterClients
+/** Not for user extension */
+@DoNotInherit sealed abstract class SubscribeClusterClients
 
 /**
  * Subscribe to a cluster receptionist's client interactions where
@@ -828,7 +839,8 @@ case object SubscribeClusterClients extends 
SubscribeClusterClients {
   def getInstance = this
 }
 
-sealed abstract class UnsubscribeClusterClients
+/** Not for user extension */
+@DoNotInherit sealed abstract class UnsubscribeClusterClients
 
 /**
  * Explicitly unsubscribe from client interaction events.
@@ -841,7 +853,8 @@ case object UnsubscribeClusterClients extends 
UnsubscribeClusterClients {
   def getInstance = this
 }
 
-sealed abstract class GetClusterClients
+/** Not for user extension */
+@DoNotInherit sealed abstract class GetClusterClients
 
 /**
  * Get the cluster clients known to this receptionist. A ``ClusterClients`` 
message
diff --git 
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/pubsub/DistributedPubSubMediator.scala
 
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/pubsub/DistributedPubSubMediator.scala
index 11dadf53fb..139c869cba 100644
--- 
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/pubsub/DistributedPubSubMediator.scala
+++ 
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/pubsub/DistributedPubSubMediator.scala
@@ -219,7 +219,8 @@ object DistributedPubSubMediator {
     override def message: Any = msg
   }
 
-  sealed abstract class GetTopics
+  /** Not for user extension */
+  @DoNotInherit sealed abstract class GetTopics
 
   /**
    * Send this message to the mediator and it will reply with
@@ -251,7 +252,8 @@ object DistributedPubSubMediator {
     }
   }
 
-  sealed abstract class Count
+  /** Not for user extension */
+  @DoNotInherit sealed abstract class Count
 
   /**
    * Scala API: Send this message to the mediator and it will reply with an 
`Int` of
diff --git 
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/singleton/ClusterSingletonManager.scala
 
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/singleton/ClusterSingletonManager.scala
index 6727f883aa..6c720e2b11 100644
--- 
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/singleton/ClusterSingletonManager.scala
+++ 
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/singleton/ClusterSingletonManager.scala
@@ -167,8 +167,10 @@ final class ClusterSingletonManagerSettings(
 
 /**
  * Marker trait for remote messages with special serializer.
+ *
+ * Not for user extension
  */
-sealed trait ClusterSingletonMessage extends Serializable
+@DoNotInherit sealed trait ClusterSingletonMessage extends Serializable
 
 object ClusterSingletonManager {
 
diff --git 
a/cluster-typed/src/main/scala/org/apache/pekko/cluster/ddata/typed/javadsl/Replicator.scala
 
b/cluster-typed/src/main/scala/org/apache/pekko/cluster/ddata/typed/javadsl/Replicator.scala
index c6b536a5d1..3c019c7f5d 100644
--- 
a/cluster-typed/src/main/scala/org/apache/pekko/cluster/ddata/typed/javadsl/Replicator.scala
+++ 
b/cluster-typed/src/main/scala/org/apache/pekko/cluster/ddata/typed/javadsl/Replicator.scala
@@ -51,7 +51,8 @@ object Replicator {
 
   @DoNotInherit trait Command extends 
pekko.cluster.ddata.typed.scaladsl.Replicator.Command
 
-  sealed trait ReadConsistency {
+  /** Not for user extension */
+  @DoNotInherit sealed trait ReadConsistency {
     def timeout: Duration
 
     /** INTERNAL API */
@@ -81,7 +82,8 @@ object Replicator {
     @InternalApi private[pekko] override def toClassic = 
dd.Replicator.ReadAll(timeout.toScala)
   }
 
-  sealed trait WriteConsistency {
+  /** Not for user extension */
+  @DoNotInherit sealed trait WriteConsistency {
     def timeout: Duration
 
     /** INTERNAL API */
@@ -281,8 +283,10 @@ object Replicator {
 
   /**
    * @see [[Replicator.Subscribe]]
+   *
+   * Not for user extension
    */
-  sealed trait SubscribeResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
+  @DoNotInherit sealed trait SubscribeResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
     def key: Key[A]
   }
 
@@ -328,7 +332,8 @@ object Replicator {
       replyTo: ActorRef[DeleteResponse[A]])
       extends Command
 
-  sealed trait DeleteResponse[A <: ReplicatedData] {
+  /** Not for user extension */
+  @DoNotInherit sealed trait DeleteResponse[A <: ReplicatedData] {
     def key: Key[A]
   }
   final case class DeleteSuccess[A <: ReplicatedData](key: Key[A]) extends 
DeleteResponse[A]
diff --git a/cluster/src/main/scala/org/apache/pekko/cluster/ClusterEvent.scala 
b/cluster/src/main/scala/org/apache/pekko/cluster/ClusterEvent.scala
index 48559f3195..679ab3eb9c 100644
--- a/cluster/src/main/scala/org/apache/pekko/cluster/ClusterEvent.scala
+++ b/cluster/src/main/scala/org/apache/pekko/cluster/ClusterEvent.scala
@@ -38,7 +38,10 @@ import pekko.event.EventStream
  */
 object ClusterEvent {
 
-  sealed abstract class SubscriptionInitialStateMode
+  /**
+   * Not for user extension
+   */
+  @DoNotInherit sealed abstract class SubscriptionInitialStateMode
 
   /**
    * When using this subscription mode a snapshot of
@@ -259,8 +262,10 @@ object ClusterEvent {
    * The state change was performed by the leader when there was
    * convergence on the leader node, i.e. all members had seen previous
    * state.
+   *
+   * Not for user extension
    */
-  sealed trait MemberEvent extends ClusterDomainEvent {
+  @DoNotInherit sealed trait MemberEvent extends ClusterDomainEvent {
     def member: Member
   }
 
@@ -373,8 +378,10 @@ object ClusterEvent {
   /**
    * Marker interface to facilitate subscription of
    * both [[UnreachableMember]] and [[ReachableMember]].
+   *
+   * Not for user extension
    */
-  sealed trait ReachabilityEvent extends ClusterDomainEvent {
+  @DoNotInherit sealed trait ReachabilityEvent extends ClusterDomainEvent {
     def member: Member
   }
 
@@ -393,8 +400,10 @@ object ClusterEvent {
   /**
    * Marker interface to facilitate subscription of
    * both [[UnreachableDataCenter]] and [[ReachableDataCenter]].
+   *
+   * Not for user extension
    */
-  sealed trait DataCenterReachabilityEvent extends ClusterDomainEvent
+  @DoNotInherit sealed trait DataCenterReachabilityEvent extends 
ClusterDomainEvent
 
   /**
    * A data center is considered as unreachable when any members from the data 
center are unreachable
diff --git a/cluster/src/main/scala/org/apache/pekko/cluster/Member.scala 
b/cluster/src/main/scala/org/apache/pekko/cluster/Member.scala
index b4a1649dd8..fc2be64798 100644
--- a/cluster/src/main/scala/org/apache/pekko/cluster/Member.scala
+++ b/cluster/src/main/scala/org/apache/pekko/cluster/Member.scala
@@ -18,7 +18,7 @@ import scala.runtime.AbstractFunction2
 
 import org.apache.pekko
 import pekko.actor.Address
-import pekko.annotation.InternalApi
+import pekko.annotation.{ DoNotInherit, InternalApi }
 import pekko.cluster.ClusterSettings.DataCenter
 import pekko.cluster.MemberStatus._
 import pekko.util.Version
@@ -234,8 +234,10 @@ object Member {
  * Defines the current status of a cluster member node
  *
  * Can be one of: Joining, WeaklyUp, Up, Leaving, Exiting and Down and Removed.
+ *
+ * Not for user extension
  */
-sealed abstract class MemberStatus
+@DoNotInherit sealed abstract class MemberStatus
 
 object MemberStatus {
   @SerialVersionUID(1L) case object Joining extends MemberStatus
diff --git 
a/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/ORMap.scala 
b/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/ORMap.scala
index db9a5e4499..c7ff8dece2 100644
--- a/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/ORMap.scala
+++ b/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/ORMap.scala
@@ -16,6 +16,7 @@ package org.apache.pekko.cluster.ddata
 import scala.collection.immutable
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.cluster.UniqueAddress
 import pekko.cluster.ddata.ORMap.ZeroTag
@@ -36,7 +37,9 @@ object ORMap {
    */
   def unapply[A, B <: ReplicatedData](m: ORMap[A, B]): Option[Map[A, B]] = 
Some(m.entries)
 
-  sealed trait DeltaOp extends ReplicatedDelta with 
RequiresCausalDeliveryOfDeltas with ReplicatedDataSerialization {
+  /** Not for user extension */
+  @DoNotInherit sealed trait DeltaOp extends ReplicatedDelta with 
RequiresCausalDeliveryOfDeltas
+      with ReplicatedDataSerialization {
     type T = DeltaOp
     override def zero: DeltaReplicatedData
   }
diff --git 
a/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/ORSet.scala 
b/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/ORSet.scala
index 37510f7267..d22f853af3 100644
--- a/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/ORSet.scala
+++ b/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/ORSet.scala
@@ -36,6 +36,7 @@ import scala.annotation.tailrec
 import scala.collection.immutable
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.cluster.UniqueAddress
 import pekko.util.HashCode
@@ -68,7 +69,9 @@ object ORSet {
    */
   @InternalApi private[pekko] type Dot = VersionVector
 
-  sealed trait DeltaOp extends ReplicatedDelta with 
RequiresCausalDeliveryOfDeltas with ReplicatedDataSerialization {
+  /** Not for user extension */
+  @DoNotInherit sealed trait DeltaOp extends ReplicatedDelta with 
RequiresCausalDeliveryOfDeltas
+      with ReplicatedDataSerialization {
     type T = DeltaOp
   }
 
diff --git 
a/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/Replicator.scala
 
b/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/Replicator.scala
index 45f80f152c..0546661029 100644
--- 
a/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/Replicator.scala
+++ 
b/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/Replicator.scala
@@ -51,6 +51,7 @@ import pekko.actor.Props
 import pekko.actor.ReceiveTimeout
 import pekko.actor.SupervisorStrategy
 import pekko.actor.Terminated
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.cluster.Cluster
 import pekko.cluster.ClusterEvent._
@@ -370,7 +371,8 @@ object Replicator {
 
   val DefaultMajorityMinCap: Int = 0
 
-  sealed trait ReadConsistency {
+  /** Not for user extension */
+  @DoNotInherit sealed trait ReadConsistency {
     def timeout: FiniteDuration
   }
   case object ReadLocal extends ReadConsistency {
@@ -414,7 +416,8 @@ object Replicator {
     def this(timeout: java.time.Duration) = this(timeout.toScala)
   }
 
-  sealed trait WriteConsistency {
+  /** Not for user extension */
+  @DoNotInherit sealed trait WriteConsistency {
     def timeout: FiniteDuration
   }
   case object WriteLocal extends WriteConsistency {
@@ -488,7 +491,8 @@ object Replicator {
     }
   }
 
-  sealed trait Command[A <: ReplicatedData] {
+  /** Not for user extension */
+  @DoNotInherit sealed trait Command[A <: ReplicatedData] {
     def key: Key[A]
   }
 
@@ -516,7 +520,9 @@ object Replicator {
       this(key, consistency, Option(request.orElse(null)))
 
   }
-  sealed abstract class GetResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
+
+  /** Not for user extension */
+  @DoNotInherit sealed abstract class GetResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
     def key: Key[A]
     def request: Option[Any]
 
@@ -594,8 +600,10 @@ object Replicator {
 
   /**
    * @see [[Replicator.Subscribe]]
+   *
+   * Not for user extension
    */
-  sealed trait SubscribeResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
+  @DoNotInherit sealed trait SubscribeResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
     def key: Key[A]
   }
 
@@ -712,7 +720,8 @@ object Replicator {
 
   }
 
-  sealed abstract class UpdateResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
+  /** Not for user extension */
+  @DoNotInherit sealed abstract class UpdateResponse[A <: ReplicatedData] 
extends NoSerializationVerificationNeeded {
     def key: Key[A]
     def request: Option[Any]
 
@@ -722,7 +731,9 @@ object Replicator {
   final case class UpdateSuccess[A <: ReplicatedData](key: Key[A], request: 
Option[Any])
       extends UpdateResponse[A]
       with DeadLetterSuppression
-  sealed abstract class UpdateFailure[A <: ReplicatedData] extends 
UpdateResponse[A]
+
+  /** Not for user extension */
+  @DoNotInherit sealed abstract class UpdateFailure[A <: ReplicatedData] 
extends UpdateResponse[A]
 
   /**
    * The direct replication of the [[Update]] could not be fulfill according to
@@ -789,7 +800,8 @@ object Replicator {
       this(key, consistency, Option(request.orElse(null)))
   }
 
-  sealed trait DeleteResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
+  /** Not for user extension */
+  @DoNotInherit sealed trait DeleteResponse[A <: ReplicatedData] extends 
NoSerializationVerificationNeeded {
     def key: Key[A]
     def request: Option[Any]
 
diff --git 
a/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/VersionVector.scala
 
b/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/VersionVector.scala
index ce6e47c8c3..64183f541f 100644
--- 
a/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/VersionVector.scala
+++ 
b/distributed-data/src/main/scala/org/apache/pekko/cluster/ddata/VersionVector.scala
@@ -19,6 +19,7 @@ import scala.annotation.tailrec
 import scala.collection.immutable.TreeMap
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.cluster.UniqueAddress
 
@@ -50,7 +51,8 @@ object VersionVector {
    */
   def create(): VersionVector = empty
 
-  sealed trait Ordering
+  /** Not for user extension */
+  @DoNotInherit sealed trait Ordering
   case object After extends Ordering
   case object Before extends Ordering
   case object Same extends Ordering
@@ -106,9 +108,12 @@ object VersionVector {
  * Based on code from `org.apache.pekko.cluster.VectorClock`.
  *
  * This class is immutable, i.e. "modifying" methods return a new instance.
+ *
+ * Not for user extension
  */
 @SerialVersionUID(1L)
-sealed abstract class VersionVector extends ReplicatedData with 
ReplicatedDataSerialization with RemovedNodePruning {
+@DoNotInherit sealed abstract class VersionVector extends ReplicatedData with 
ReplicatedDataSerialization
+    with RemovedNodePruning {
 
   type T = VersionVector
 
diff --git 
a/persistence-tck/src/main/scala/org/apache/pekko/persistence/CapabilityFlags.scala
 
b/persistence-tck/src/main/scala/org/apache/pekko/persistence/CapabilityFlags.scala
index 3f866e656a..229702f315 100644
--- 
a/persistence-tck/src/main/scala/org/apache/pekko/persistence/CapabilityFlags.scala
+++ 
b/persistence-tck/src/main/scala/org/apache/pekko/persistence/CapabilityFlags.scala
@@ -17,7 +17,11 @@ import scala.language.implicitConversions
 import scala.jdk.CollectionConverters._
 import scala.util.Try
 
-sealed abstract class CapabilityFlag {
+import org.apache.pekko
+import pekko.annotation.DoNotInherit
+
+/** Not for user extension */
+@DoNotInherit sealed abstract class CapabilityFlag {
   private val capturedStack: String =
     StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk { 
stream =>
       stream.iterator().asScala
diff --git 
a/persistence-testkit/src/main/scala/org/apache/pekko/persistence/testkit/ProcessingPolicy.scala
 
b/persistence-testkit/src/main/scala/org/apache/pekko/persistence/testkit/ProcessingPolicy.scala
index db9214be27..3276dd320f 100644
--- 
a/persistence-testkit/src/main/scala/org/apache/pekko/persistence/testkit/ProcessingPolicy.scala
+++ 
b/persistence-testkit/src/main/scala/org/apache/pekko/persistence/testkit/ProcessingPolicy.scala
@@ -16,7 +16,7 @@ package org.apache.pekko.persistence.testkit
 import scala.util.control.NoStackTrace
 
 import org.apache.pekko
-import pekko.annotation.{ ApiMayChange, InternalApi }
+import pekko.annotation.{ ApiMayChange, DoNotInherit, InternalApi }
 
 /**
  * Policies allow to emulate behavior of the storage (failures and rejections).
@@ -156,7 +156,8 @@ sealed trait ProcessingFailure extends ProcessingResult {
 
 }
 
-sealed abstract class ExpectedRejection extends Throwable
+/** Not for user extension */
+@DoNotInherit sealed abstract class ExpectedRejection extends Throwable
 
 object ExpectedRejection extends ExpectedRejection {
 
@@ -164,7 +165,8 @@ object ExpectedRejection extends ExpectedRejection {
 
 }
 
-sealed abstract class ExpectedFailure extends Throwable with NoStackTrace
+/** Not for user extension */
+@DoNotInherit sealed abstract class ExpectedFailure extends Throwable with 
NoStackTrace
 
 object ExpectedFailure extends ExpectedFailure {
 
diff --git 
a/persistence-testkit/src/main/scala/org/apache/pekko/persistence/testkit/scaladsl/PersistenceProbeBehavior.scala
 
b/persistence-testkit/src/main/scala/org/apache/pekko/persistence/testkit/scaladsl/PersistenceProbeBehavior.scala
index bf02b70f35..3af5e90e40 100644
--- 
a/persistence-testkit/src/main/scala/org/apache/pekko/persistence/testkit/scaladsl/PersistenceProbeBehavior.scala
+++ 
b/persistence-testkit/src/main/scala/org/apache/pekko/persistence/testkit/scaladsl/PersistenceProbeBehavior.scala
@@ -21,7 +21,8 @@ import pekko.actor.typed.Behavior
 import pekko.annotation.DoNotInherit
 import pekko.persistence.testkit.internal.PersistenceProbeImpl
 
-sealed trait PersistenceProbeBehavior[Command, State] {
+/** Not for user extension */
+@DoNotInherit sealed trait PersistenceProbeBehavior[Command, State] {
   val behavior: Behavior[Command]
   lazy val behaviorTestKit = BehaviorTestKit(behavior)
 
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/EventAdapter.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/EventAdapter.scala
index 6d9c9fc643..8153371497 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/EventAdapter.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/EventAdapter.scala
@@ -17,6 +17,7 @@ import scala.annotation.varargs
 import scala.collection.immutable
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 
 /**
@@ -75,7 +76,8 @@ abstract class EventAdapter[E, P] {
   def fromJournal(p: P, manifest: String): EventSeq[E]
 }
 
-sealed trait EventSeq[+A] {
+/** Not for user extension */
+@DoNotInherit sealed trait EventSeq[+A] {
   def events: immutable.Seq[A]
   def isEmpty: Boolean = events.isEmpty
   def nonEmpty: Boolean = events.nonEmpty
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/crdt/ORSet.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/crdt/ORSet.scala
index 938d4f7b85..1d3c6198b9 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/crdt/ORSet.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/crdt/ORSet.scala
@@ -17,6 +17,7 @@ import scala.annotation.tailrec
 import scala.collection.immutable
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.persistence.typed.ReplicaId
 import pekko.persistence.typed.crdt.ORSet.DeltaOp
@@ -42,7 +43,8 @@ object ORSet {
    */
   @InternalApi private[pekko] type Dot = VersionVector
 
-  sealed trait DeltaOp {
+  /** Not for user extension */
+  @DoNotInherit sealed trait DeltaOp {
     def merge(that: DeltaOp): DeltaOp
   }
 
diff --git 
a/persistence/src/main/scala/org/apache/pekko/persistence/PersistentActor.scala 
b/persistence/src/main/scala/org/apache/pekko/persistence/PersistentActor.scala
index 239999d84d..17ada6f8c7 100644
--- 
a/persistence/src/main/scala/org/apache/pekko/persistence/PersistentActor.scala
+++ 
b/persistence/src/main/scala/org/apache/pekko/persistence/PersistentActor.scala
@@ -20,6 +20,7 @@ import scala.util.control.NoStackTrace
 
 import org.apache.pekko
 import pekko.actor._
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.japi.Util
 import pekko.japi.function.Procedure
@@ -118,8 +119,10 @@ final class RecoveryTimedOut(message: String) extends 
RuntimeException(message)
 /**
  * This defines how to handle the current received message which failed to 
stash, when the size of
  * Stash exceeding the capacity of Stash.
+ *
+ * Not for user extension
  */
-sealed trait StashOverflowStrategy
+@DoNotInherit sealed trait StashOverflowStrategy
 
 /**
  * Discard the message to [[pekko.actor.DeadLetter]].
diff --git 
a/persistence/src/main/scala/org/apache/pekko/persistence/journal/EventAdapter.scala
 
b/persistence/src/main/scala/org/apache/pekko/persistence/journal/EventAdapter.scala
index 547a563b10..3b0daa5e0b 100644
--- 
a/persistence/src/main/scala/org/apache/pekko/persistence/journal/EventAdapter.scala
+++ 
b/persistence/src/main/scala/org/apache/pekko/persistence/journal/EventAdapter.scala
@@ -16,6 +16,9 @@ package org.apache.pekko.persistence.journal
 import scala.annotation.varargs
 import scala.collection.immutable
 
+import org.apache.pekko
+import pekko.annotation.DoNotInherit
+
 /**
  * An [[EventAdapter]] is both a [[WriteEventAdapter]] and a 
[[ReadEventAdapter]].
  * Facility to convert from and to specialised data models, as may be required 
by specialized persistence Journals.
@@ -93,7 +96,8 @@ trait ReadEventAdapter {
   // #event-adapter-api
 }
 
-sealed abstract class EventSeq {
+/** Not for user extension */
+@DoNotInherit sealed abstract class EventSeq {
   def events: immutable.Seq[Any]
 }
 object EventSeq {
@@ -113,7 +117,8 @@ final case class SingleEventSeq(event: Any) extends 
EventSeq { // TODO try to ma
   override def toString = s"SingleEventSeq($event)"
 }
 
-sealed trait EmptyEventSeq extends EventSeq
+/** Not for user extension */
+@DoNotInherit sealed trait EmptyEventSeq extends EventSeq
 object EmptyEventSeq extends EmptyEventSeq {
   override def events = Nil
 }
diff --git 
a/stream-testkit/src/main/scala/org/apache/pekko/stream/testkit/TestGraphStage.scala
 
b/stream-testkit/src/main/scala/org/apache/pekko/stream/testkit/TestGraphStage.scala
index 459ba03fcc..30a38b00c5 100644
--- 
a/stream-testkit/src/main/scala/org/apache/pekko/stream/testkit/TestGraphStage.scala
+++ 
b/stream-testkit/src/main/scala/org/apache/pekko/stream/testkit/TestGraphStage.scala
@@ -17,6 +17,7 @@ import scala.util.control.NonFatal
 
 import org.apache.pekko
 import pekko.actor.NoSerializationVerificationNeeded
+import pekko.annotation.DoNotInherit
 import pekko.stream._
 import pekko.stream.scaladsl.{ Sink, Source }
 import pekko.stream.stage.{ GraphStageWithMaterializedValue, InHandler, 
OutHandler }
@@ -26,7 +27,9 @@ import pekko.testkit.TestProbe
  * Messages emitted after the corresponding `stageUnderTest` methods has been 
invoked.
  */
 object GraphStageMessages {
-  sealed trait StageMessage
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait StageMessage
   case object Push extends StageMessage with NoSerializationVerificationNeeded
   case object UpstreamFinish extends StageMessage with 
NoSerializationVerificationNeeded
   case class Failure(ex: Throwable) extends StageMessage with 
NoSerializationVerificationNeeded
diff --git 
a/stream/src/main/scala/org/apache/pekko/stream/ActorMaterializer.scala 
b/stream/src/main/scala/org/apache/pekko/stream/ActorMaterializer.scala
index 2a3d85060f..3257e5721b 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/ActorMaterializer.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/ActorMaterializer.scala
@@ -24,6 +24,7 @@ import pekko.actor.ActorRef
 import pekko.actor.ActorRefFactory
 import pekko.actor.ActorSystem
 import pekko.actor.ExtendedActorSystem
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.stream.impl._
 import pekko.stream.impl.streamref.StreamRefDefaultSettings
@@ -416,8 +417,9 @@ final class StreamSubscriptionTimeoutSettings(
 /**
  * This mode describes what shall happen when the subscription timeout expires 
for
  * substream Publishers created by operations like `prefixAndTail`.
+ * Not for user extension
  */
-sealed abstract class StreamSubscriptionTimeoutTerminationMode
+@DoNotInherit sealed abstract class StreamSubscriptionTimeoutTerminationMode
 
 object StreamSubscriptionTimeoutTerminationMode {
   case object NoopTermination extends StreamSubscriptionTimeoutTerminationMode
diff --git a/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala 
b/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
index 5cb9235886..36583c971c 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
@@ -454,7 +454,8 @@ object Attributes {
   object CancellationStrategy {
     private[stream] val Default: CancellationStrategy = 
CancellationStrategy(PropagateFailure)
 
-    sealed trait Strategy
+    /** Not for user extension */
+    @DoNotInherit sealed trait Strategy
 
     /**
      * Strategy that treats `cancelStage` the same as `completeStage`, i.e. 
all inlets are cancelled (propagating the
diff --git a/stream/src/main/scala/org/apache/pekko/stream/FanInShape.scala 
b/stream/src/main/scala/org/apache/pekko/stream/FanInShape.scala
index 3fd6d73497..6ca0d77417 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/FanInShape.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/FanInShape.scala
@@ -16,8 +16,12 @@ package org.apache.pekko.stream
 import scala.annotation.unchecked.uncheckedVariance
 import scala.collection.immutable
 
+import org.apache.pekko.annotation.DoNotInherit
+
 object FanInShape {
-  sealed trait Init[O] {
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait Init[O] {
     def outlet: Outlet[O]
     def inlets: immutable.Seq[Inlet[?]]
     def name: String
diff --git a/stream/src/main/scala/org/apache/pekko/stream/FanOutShape.scala 
b/stream/src/main/scala/org/apache/pekko/stream/FanOutShape.scala
index 765387916c..efdec76f87 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/FanOutShape.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/FanOutShape.scala
@@ -16,8 +16,12 @@ package org.apache.pekko.stream
 import scala.annotation.unchecked.uncheckedVariance
 import scala.collection.immutable
 
+import org.apache.pekko.annotation.DoNotInherit
+
 object FanOutShape {
-  sealed trait Init[I] {
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait Init[I] {
     def inlet: Inlet[I]
     def outlets: immutable.Seq[Outlet[?]]
     def name: String
diff --git a/stream/src/main/scala/org/apache/pekko/stream/FlowMonitor.scala 
b/stream/src/main/scala/org/apache/pekko/stream/FlowMonitor.scala
index 6e940d23ec..ada9aa3b12 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/FlowMonitor.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/FlowMonitor.scala
@@ -14,6 +14,7 @@
 package org.apache.pekko.stream
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.stream.FlowMonitorState.StreamState
 
 /**
@@ -26,7 +27,9 @@ trait FlowMonitor[+T] {
 }
 
 object FlowMonitorState {
-  sealed trait StreamState[+U]
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait StreamState[+U]
 
   /**
    * Stream was created, but no events have passed through it
diff --git a/stream/src/main/scala/org/apache/pekko/stream/Shape.scala 
b/stream/src/main/scala/org/apache/pekko/stream/Shape.scala
index bd4253edc8..8271ada14b 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/Shape.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/Shape.scala
@@ -18,6 +18,7 @@ import scala.collection.immutable
 import scala.jdk.CollectionConverters._
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.util.Collections.EmptyImmutableSeq
 
@@ -26,8 +27,9 @@ import pekko.util.Collections.EmptyImmutableSeq
  * into the impl package but must live here due to how `sealed` works.
  * It is also used in the Java DSL for “classic Inlets” as a work-around
  * for otherwise unreasonable existential types.
+ * Not for user extension
  */
-sealed abstract class InPort { self: Inlet[?] =>
+@DoNotInherit sealed abstract class InPort { self: Inlet[?] =>
   final override def hashCode: Int = super.hashCode
   final override def equals(that: Any): Boolean = this eq 
that.asInstanceOf[AnyRef]
 
@@ -52,8 +54,9 @@ sealed abstract class InPort { self: Inlet[?] =>
  * into the impl package but must live here due to how `sealed` works.
  * It is also used in the Java DSL for “classic Outlets” as a work-around
  * for otherwise unreasonable existential types.
+ * Not for user extension
  */
-sealed abstract class OutPort { self: Outlet[?] =>
+@DoNotInherit sealed abstract class OutPort { self: Outlet[?] =>
   final override def hashCode: Int = super.hashCode
   final override def equals(that: Any): Boolean = this eq 
that.asInstanceOf[AnyRef]
 
@@ -262,8 +265,9 @@ abstract class AbstractShape extends Shape {
 /**
  * This [[Shape]] is used for graphs that have neither open inputs nor open
  * outputs. Only such a [[Graph]] can be materialized by a [[Materializer]].
+ * Not for user extension
  */
-sealed abstract class ClosedShape extends Shape
+@DoNotInherit sealed abstract class ClosedShape extends Shape
 object ClosedShape extends ClosedShape {
   override val inlets: immutable.Seq[Inlet[?]] = EmptyImmutableSeq
   override val outlets: immutable.Seq[Outlet[?]] = EmptyImmutableSeq
diff --git a/stream/src/main/scala/org/apache/pekko/stream/SslTlsOptions.scala 
b/stream/src/main/scala/org/apache/pekko/stream/SslTlsOptions.scala
index 964001c6fc..90f2490815 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/SslTlsOptions.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/SslTlsOptions.scala
@@ -19,6 +19,7 @@ import scala.annotation.varargs
 import scala.collection.immutable
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.util.ByteString
 
 /**
@@ -38,20 +39,24 @@ object TLSRole {
    */
   def server: TLSRole = Server
 }
-sealed abstract class TLSRole
+
+/** Not for user extension */
+@DoNotInherit sealed abstract class TLSRole
 
 /**
  * The client is usually the side that consumes the service provided by its
  * interlocutor. The precise interpretation of this role is protocol specific.
+ * Not for user extension
  */
-sealed abstract class Client extends TLSRole
+@DoNotInherit sealed abstract class Client extends TLSRole
 case object Client extends Client
 
 /**
  * The server is usually the side the provides the service to its interlocutor.
  * The precise interpretation of this role is protocol specific.
+ * Not for user extension
  */
-sealed abstract class Server extends TLSRole
+@DoNotInherit sealed abstract class Server extends TLSRole
 case object Server extends Server
 
 /**
@@ -85,8 +90,9 @@ case object Server extends Server
  *    side unless the receiving side has already canceled
  *  - [[IgnoreBoth]] means to ignore the first termination signal—be that
  *    cancellation or completion—and only act upon the second one
+ * Not for user extension
  */
-sealed abstract class TLSClosing {
+@DoNotInherit sealed abstract class TLSClosing {
   def ignoreCancel: Boolean
   def ignoreComplete: Boolean
 }
@@ -115,8 +121,9 @@ object TLSClosing {
 
 /**
  * see [[TLSClosing]]
+ * Not for user extension
  */
-sealed abstract class EagerClose extends TLSClosing {
+@DoNotInherit sealed abstract class EagerClose extends TLSClosing {
   override def ignoreCancel = false
   override def ignoreComplete = false
 }
@@ -124,8 +131,9 @@ case object EagerClose extends EagerClose
 
 /**
  * see [[TLSClosing]]
+ * Not for user extension
  */
-sealed abstract class IgnoreCancel extends TLSClosing {
+@DoNotInherit sealed abstract class IgnoreCancel extends TLSClosing {
   override def ignoreCancel = true
   override def ignoreComplete = false
 }
@@ -133,8 +141,9 @@ case object IgnoreCancel extends IgnoreCancel
 
 /**
  * see [[TLSClosing]]
+ * Not for user extension
  */
-sealed abstract class IgnoreComplete extends TLSClosing {
+@DoNotInherit sealed abstract class IgnoreComplete extends TLSClosing {
   override def ignoreCancel = false
   override def ignoreComplete = true
 }
@@ -142,8 +151,9 @@ case object IgnoreComplete extends IgnoreComplete
 
 /**
  * see [[TLSClosing]]
+ * Not for user extension
  */
-sealed abstract class IgnoreBoth extends TLSClosing {
+@DoNotInherit sealed abstract class IgnoreBoth extends TLSClosing {
   override def ignoreCancel = true
   override def ignoreComplete = true
 }
@@ -154,8 +164,9 @@ object TLSProtocol {
   /**
    * This is the supertype of all messages that the SslTls operator emits on 
the
    * plaintext side.
+   * Not for user extension
    */
-  sealed trait SslTlsInbound
+  @DoNotInherit sealed trait SslTlsInbound
 
   /**
    * If the underlying transport is closed before the final TLS closure command
@@ -164,8 +175,9 @@ object TLSProtocol {
    * translated into this message when encountered. Most of the time this 
occurs
    * not because of a malicious attacker but due to a connection abort or a
    * misbehaving communication peer.
+   * Not for user extension
    */
-  sealed abstract class SessionTruncated extends SslTlsInbound
+  @DoNotInherit sealed abstract class SessionTruncated extends SslTlsInbound
 
   case object SessionTruncated extends SessionTruncated
 
@@ -186,8 +198,9 @@ object TLSProtocol {
   /**
    * This is the supertype of all messages that the SslTls operator accepts on 
its
    * plaintext side.
+   * Not for user extension
    */
-  sealed trait SslTlsOutbound
+  @DoNotInherit sealed trait SslTlsOutbound
 
   /**
    * Initiate a new session negotiation. Any [[SendBytes]] commands following
@@ -269,8 +282,9 @@ object TLSProtocol {
  * verification.
  *
  * See the documentation for `SSLEngine::setWantClientAuth` for more 
information.
+ * Not for user extension
  */
-sealed abstract class TLSClientAuth
+@DoNotInherit sealed abstract class TLSClientAuth
 object TLSClientAuth {
   case object None extends TLSClientAuth
   case object Want extends TLSClientAuth
diff --git a/stream/src/main/scala/org/apache/pekko/stream/Supervision.scala 
b/stream/src/main/scala/org/apache/pekko/stream/Supervision.scala
index a60c678a5b..c23bc896e5 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/Supervision.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/Supervision.scala
@@ -14,10 +14,13 @@
 package org.apache.pekko.stream
 
 import org.apache.pekko
+import pekko.annotation.DoNotInherit
 import pekko.japi.{ function => japi }
 
 object Supervision {
-  sealed trait Directive
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait Directive
 
   /**
    * Scala API: The stream will be completed with failure if application code 
for processing an element
diff --git a/stream/src/main/scala/org/apache/pekko/stream/ThrottleMode.scala 
b/stream/src/main/scala/org/apache/pekko/stream/ThrottleMode.scala
index c237b91200..bedd7e3071 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/ThrottleMode.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/ThrottleMode.scala
@@ -13,10 +13,13 @@
 
 package org.apache.pekko.stream
 
+import org.apache.pekko.annotation.DoNotInherit
+
 /**
  * Represents a mode that decides how to deal exceed rate for Throttle operator
+ * Not for user extension
  */
-sealed abstract class ThrottleMode
+@DoNotInherit sealed abstract class ThrottleMode
 
 object ThrottleMode {
 
diff --git a/stream/src/main/scala/org/apache/pekko/stream/scaladsl/Graph.scala 
b/stream/src/main/scala/org/apache/pekko/stream/scaladsl/Graph.scala
index 5135f15651..d7d77b8c9c 100755
--- a/stream/src/main/scala/org/apache/pekko/stream/scaladsl/Graph.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/scaladsl/Graph.scala
@@ -23,6 +23,7 @@ import scala.util.control.{ NoStackTrace, NonFatal }
 
 import org.apache.pekko
 import pekko.NotUsed
+import pekko.annotation.DoNotInherit
 import pekko.annotation.InternalApi
 import pekko.stream._
 import pekko.stream.ActorAttributes.SupervisionStrategy
@@ -1841,7 +1842,8 @@ object GraphDSL extends GraphApply {
       else junction.in(n)
     }
 
-    sealed trait CombinerBase[+T] extends Any {
+    /** Not for user extension */
+    @DoNotInherit sealed trait CombinerBase[+T] extends Any {
       def importAndGetPort(b: Builder[?]): Outlet[T @uncheckedVariance]
 
       def ~>[U >: T](to: Inlet[U])(implicit b: Builder[?]): Unit =
@@ -1884,7 +1886,8 @@ object GraphDSL extends GraphApply {
         b.addEdge(importAndGetPort(b), to.in)
     }
 
-    sealed trait ReverseCombinerBase[T] extends Any {
+    /** Not for user extension */
+    @DoNotInherit sealed trait ReverseCombinerBase[T] extends Any {
       def importAndGetPortReverse(b: Builder[?]): Inlet[T]
 
       def <~[U <: T](from: Outlet[U])(implicit b: Builder[?]): Unit =
diff --git a/stream/src/main/scala/org/apache/pekko/stream/scaladsl/Hub.scala 
b/stream/src/main/scala/org/apache/pekko/stream/scaladsl/Hub.scala
index 26720b05ec..eee1129ad7 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/scaladsl/Hub.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/scaladsl/Hub.scala
@@ -51,8 +51,9 @@ object MergeHub {
   /**
    * A DrainingControl object is created during the materialization of a 
MergeHub and allows to initiate the draining
    * and eventual completion of the Hub from the outside.
+   * Not for user extension
    */
-  sealed trait DrainingControl {
+  @DoNotInherit sealed trait DrainingControl {
 
     /**
      * Set the operation mode of the linked MergeHub to draining. In this mode 
the Hub will cancel any new producer and
diff --git 
a/stream/src/main/scala/org/apache/pekko/stream/snapshot/MaterializerState.scala
 
b/stream/src/main/scala/org/apache/pekko/stream/snapshot/MaterializerState.scala
index e22bf92020..f105bfe798 100644
--- 
a/stream/src/main/scala/org/apache/pekko/stream/snapshot/MaterializerState.scala
+++ 
b/stream/src/main/scala/org/apache/pekko/stream/snapshot/MaterializerState.scala
@@ -160,7 +160,9 @@ sealed trait LogicSnapshot {
 
 @ApiMayChange
 object ConnectionSnapshot {
-  sealed trait ConnectionState
+
+  /** Not for user extension */
+  @DoNotInherit sealed trait ConnectionState
   case object ShouldPull extends ConnectionState
   case object ShouldPush extends ConnectionState
   case object Closed extends ConnectionState
diff --git a/testkit/src/main/scala/org/apache/pekko/testkit/SocketUtil.scala 
b/testkit/src/main/scala/org/apache/pekko/testkit/SocketUtil.scala
index 8acf66ad5b..df3c6b4fa3 100644
--- a/testkit/src/main/scala/org/apache/pekko/testkit/SocketUtil.scala
+++ b/testkit/src/main/scala/org/apache/pekko/testkit/SocketUtil.scala
@@ -21,6 +21,9 @@ import scala.collection.immutable
 import scala.util.Random
 import scala.util.control.NonFatal
 
+import org.apache.pekko
+import pekko.annotation.DoNotInherit
+
 /**
  * Utilities to get free socket address.
  */
@@ -37,7 +40,8 @@ object SocketUtil {
     }
   }
 
-  sealed trait Protocol
+  /** Not for user extension */
+  @DoNotInherit sealed trait Protocol
   case object Tcp extends Protocol
   case object Udp extends Protocol
   case object Both extends Protocol
diff --git 
a/testkit/src/main/scala/org/apache/pekko/testkit/TestEventListener.scala 
b/testkit/src/main/scala/org/apache/pekko/testkit/TestEventListener.scala
index 3941907511..919113322c 100644
--- a/testkit/src/main/scala/org/apache/pekko/testkit/TestEventListener.scala
+++ b/testkit/src/main/scala/org/apache/pekko/testkit/TestEventListener.scala
@@ -24,6 +24,7 @@ import org.apache.pekko
 import pekko.actor.{ ActorSystem, DeadLetter, UnhandledMessage }
 import pekko.actor.Dropped
 import pekko.actor.NoSerializationVerificationNeeded
+import pekko.annotation.DoNotInherit
 import pekko.dispatch.sysmsg.{ SystemMessage, Terminate }
 import pekko.event.Logging
 import pekko.event.Logging.{ Debug, Error, Info, InitializeLogger, LogEvent, 
LoggerInitialized, Warning }
@@ -38,8 +39,10 @@ import pekko.util.BoxedType
  * You should always prefer the filter methods in the package object
  * (see `org.apache.pekko.testkit` `filterEvents` and `filterException`) or on 
the
  * EventFilter implementations.
+ *
+ * Not for user extension
  */
-sealed trait TestEvent
+@DoNotInherit sealed trait TestEvent
 
 /**
  * Implementation helpers of the EventFilter facilities: send <code>Mute</code>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to