diff --git a/swh/model/model.py b/swh/model/model.py
index c919df0d7296afa7485b209b420992489f7f25e6..0170bcaf350579c995f3f39ea36fe7ad55dd9f56 100644
--- a/swh/model/model.py
+++ b/swh/model/model.py
@@ -382,7 +382,7 @@ def _compute_hash_from_manifest(manifest: bytes) -> Sha1Git:
     return hashlib.new("sha1", manifest).digest()
 
 
-class HashableObject(metaclass=ABCMeta):
+class BaseHashableModel(BaseModel, metaclass=ABCMeta):
     """Mixin to automatically compute object identifier hash when
     the associated model is instantiated."""
 
@@ -412,14 +412,17 @@ class HashableObject(metaclass=ABCMeta):
         return self.id
 
     def check(self) -> None:
-        super().check()  # type: ignore
+        super().check()
 
         if self.id != self.compute_hash():
             raise ValueError("'id' does not match recomputed hash.")
 
 
-class HashableObjectWithManifest(HashableObject):
-    """Derived class of HashableObject, for objects that may need to store
+HashableObject = BaseHashableModel  # deprecated alias
+
+
+class HashableObjectWithManifest(BaseHashableModel):
+    """Derived class of BaseHashableModel, for objects that may need to store
     verbatim git objects as ``raw_manifest`` to preserve original hashes."""
 
     __slots__ = ()
@@ -767,7 +770,7 @@ class TimestampWithTimezone(BaseModel):
 
 
 @attr.s(frozen=True, slots=True, field_transformer=optimize_all_validators)
-class Origin(HashableObject, BaseModel):
+class Origin(BaseHashableModel):
     """Represents a software source: a VCS and an URL."""
 
     object_type: Final = "origin"
@@ -933,7 +936,7 @@ class SnapshotBranch(BaseModel):
 
 
 @attr.s(frozen=True, slots=True, field_transformer=optimize_all_validators)
-class Snapshot(HashableObject, BaseModel):
+class Snapshot(BaseHashableModel):
     """Represents the full state of an origin at a given point in time."""
 
     object_type: Final = "snapshot"
@@ -1651,7 +1654,7 @@ def normalize_discovery_date(value: Any) -> datetime.datetime:
 
 
 @attr.s(frozen=True, slots=True, field_transformer=optimize_all_validators)
-class RawExtrinsicMetadata(HashableObject, BaseModel):
+class RawExtrinsicMetadata(BaseHashableModel):
     object_type: Final = "raw_extrinsic_metadata"
 
     # target object
@@ -1897,7 +1900,7 @@ class RawExtrinsicMetadata(HashableObject, BaseModel):
 
 
 @attr.s(frozen=True, slots=True, field_transformer=optimize_all_validators)
-class ExtID(HashableObject, BaseModel):
+class ExtID(BaseHashableModel):
     object_type: Final = "extid"
 
     extid_type = attr.ib(type=str, validator=generic_type_validator)
diff --git a/swh/model/tests/test_model.py b/swh/model/tests/test_model.py
index f2adc62941d98bff9752f10f151bbb1ba87c796d..248410f99fcbce422207294493b9993c11a2106e 100644
--- a/swh/model/tests/test_model.py
+++ b/swh/model/tests/test_model.py
@@ -1509,9 +1509,13 @@ def test_object_type(objtype_and_obj):
 
 
 def test_object_type_is_final():
+    checked_classes = set()
     object_types = set()
 
     def check_final(cls):
+        if cls in checked_classes:
+            return
+        checked_classes.add(cls)
         if hasattr(cls, "object_type"):
             assert cls.object_type not in object_types
             object_types.add(cls.object_type)