Index: tests/test_composite_backend.py
===================================================================
--- tests/test_composite_backend.py	(revision a17e4f68f5171edbf6d5d7644d58b7e36f86d2dd)
+++ tests/test_composite_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -10,5 +10,5 @@
     backend = CompositeBackend(authoritative_backend=primary, sync_backends=[secondary])
 
-    backend.save(sample_domain)
+    backend.save(sample_domain.to_dict())
 
     fid = sample_domain.flexo_id
@@ -25,9 +25,9 @@
     backend = CompositeBackend(authoritative_backend=primary, sync_backends=[secondary])
 
-    primary.save(sample_domain)
+    primary.save(sample_domain.to_dict())
 
     # secondary has nothing, but composite should still load from primary
     fid = sample_domain.flexo_id
-    loaded = backend.load(fid)
+    loaded = Domain.from_dict(backend.load(fid))
     assert isinstance(loaded, Domain)
 
@@ -39,5 +39,5 @@
     backend = CompositeBackend(authoritative_backend=primary, sync_backends=[secondary])
 
-    backend.save(sample_domain)
+    backend.save(sample_domain.to_dict())
 
     backend.clear()
Index: tests/test_flexoid.py
===================================================================
--- tests/test_flexoid.py	(revision a17e4f68f5171edbf6d5d7644d58b7e36f86d2dd)
+++ tests/test_flexoid.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -13,5 +13,5 @@
 import pytest
 from logging import Logger
-from flexoentity import FlexOID, canonical_seed
+from flexoentity import FlexOID, canonical_seed, Domain
 
 
@@ -51,25 +51,36 @@
 # Generation and deterministic hashing
 # ──────────────────────────────────────────────
-
-def test_generate_and_hash_stability(fixed_datetime):
-    # Fix the date so test is stable
+def test_generate_is_not_deterministic(fixed_datetime):
     fid1 = FlexOID.generate("GEN", "I", "D", "test content")
     fid2 = FlexOID.generate("GEN", "I", "D", "test content")
-    assert fid1 == fid2  # deterministic
-    assert fid1.hash_part == fid2.hash_part
-    assert fid1.domain_id == "GEN"
-    assert fid1.entity_type == "I"
 
+    assert fid1 != fid2
+    assert fid1.domain_id == fid2.domain_id == "GEN"
+    assert fid1.entity_type == fid2.entity_type == "I"
+    assert fid1.version == fid2.version == 1
+    assert fid1.state_code == fid2.state_code == "D"
+
+def test_fingerprint_is_stable():
+    d1 = Domain.with_domain_id("GEN", fullname="A", description="B")
+    d2 = Domain.from_dict(d1.to_dict())
+
+    assert d1.fingerprint == d2.fingerprint
 
 def test_safe_generate_collision(monkeypatch):
-    # Fake repo that always returns a conflicting item with different seed
-    class DummyRepo(dict):
-        def get(self, key): return True
+    first = FlexOID.generate("GEN", "I", "D", "abc")
+
+    class DummyRepo:
+        def get(self, key):
+            if key == str(first):
+                return True
+            return None
 
     repo = DummyRepo()
+
     fid = FlexOID.safe_generate("GEN", "I", "D", "abc", repo=repo)
+
     assert isinstance(fid, FlexOID)
+    assert fid != first
     assert fid.state_code == "D"
-
 
 # ──────────────────────────────────────────────
Index: tests/test_id_stress.py
===================================================================
--- tests/test_id_stress.py	(revision a17e4f68f5171edbf6d5d7644d58b7e36f86d2dd)
+++ tests/test_id_stress.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -52,17 +52,17 @@
     assert all("@" in id_str for id_str in ids)
 
-def test_id_generation_is_deterministic(sample_domain):
-    """
-    Generating the same entity twice with same inputs yields identical ID.
-    (No runtime disambiguation; IDs are deterministic by design.)
-    """
-    entity_type = EntityType.ITEM
-    estate = EntityState.DRAFT
-    text = "identical question text"
+# def test_id_generation_is_deterministic(sample_domain):
+#     """
+#     Generating the same entity twice with same inputs yields identical ID.
+#     (No runtime disambiguation; IDs are deterministic by design.)
+#     """
+#     entity_type = EntityType.ITEM
+#     estate = EntityState.DRAFT
+#     text = "identical question text"
 
-    id1 = FlexOID.generate(sample_domain.domain_id, entity_type.value, estate.value, text)
-    id2 = FlexOID.generate(sample_domain.domain_id, entity_type.value, estate.value, text)
-    # IDs must be identical because generation is deterministic
-    assert id1 == id2
+#     id1 = FlexOID.generate(sample_domain.domain_id, entity_type.value, estate.value, text)
+#     id2 = FlexOID.generate(sample_domain.domain_id, entity_type.value, estate.value, text)
+#     # IDs must be identical because generation is deterministic
+#     assert id1 == id2
 
 def test_massive_lifecycle_simulation(cert_ref_linux, sample_domain):
Index: tests/test_in_memory_backend.py
===================================================================
--- tests/test_in_memory_backend.py	(revision a17e4f68f5171edbf6d5d7644d58b7e36f86d2dd)
+++ tests/test_in_memory_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -7,25 +7,25 @@
 
 def test_save_and_load_roundtrip(local_backend, sample_domain):
-    local_backend.save(sample_domain)
+    local_backend.save(sample_domain.to_dict())
 
-    loaded = local_backend.load(sample_domain.flexo_id)
+    loaded_dict = local_backend.load(sample_domain.flexo_id)
+    loaded = Domain.from_dict(loaded_dict)
+
     assert isinstance(loaded, Domain)
-    # important: entity equality is probably identity-based, so compare dicts:
-    assert loaded.to_dict() == sample_domain.to_dict()
-
-
+    assert loaded == sample_domain
+    
 def test_update_overwrites_entity(local_backend, sample_domain):
-    local_backend.save(sample_domain)
+    local_backend.save(sample_domain.to_dict())
 
     # change something
     sample_domain.description = "UPDATED DESC"
-    local_backend.update(sample_domain)
+    local_backend.update(sample_domain.to_dict())
 
-    loaded = local_backend.load(sample_domain.flexo_id)
+    loaded = Domain.from_dict(local_backend.load(sample_domain.flexo_id))
     assert loaded.description == "UPDATED DESC"
 
 
 def test_delete_removes_entity(local_backend, sample_domain):
-    local_backend.save(sample_domain)
+    local_backend.save(sample_domain.to_dict())
     local_backend.delete(sample_domain.flexo_id)
 
@@ -35,5 +35,5 @@
 
 def test_clear_removes_all(local_backend, sample_domain):
-    local_backend.save(sample_domain)
+    local_backend.save(sample_domain.to_dict())
     local_backend.clear()
 
Index: tests/test_json_file_backend.py
===================================================================
--- tests/test_json_file_backend.py	(revision a17e4f68f5171edbf6d5d7644d58b7e36f86d2dd)
+++ tests/test_json_file_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -22,6 +22,6 @@
     dom2 = make_domain("PY_STRINGS")
 
-    backend.save(dom1)
-    backend.save(dom2)
+    backend.save(dom1.to_dict())
+    backend.save(dom2.to_dict())
     backend.flush_to_file()
 
@@ -29,6 +29,6 @@
     backend2 = JsonFileBackend(Domain, path)
     backend2.load_from_file()
-
-    loaded = backend2.load_all()
-    ids = sorted(d.domain_id for d in loaded)
+    loaded_dicts = backend2.load_all()
+    domains = [Domain.from_dict(d) for d in loaded_dicts]
+    ids = sorted(d.domain_id for d in domains)
     assert ids == ["PY_ARITHM", "PY_STRINGS"]
Index: tests/test_sqlite_backend.py
===================================================================
--- tests/test_sqlite_backend.py	(revision a17e4f68f5171edbf6d5d7644d58b7e36f86d2dd)
+++ tests/test_sqlite_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -4,15 +4,5 @@
 
 
-def make_domain(domain_id="PY_ARITHM"):
-    return Domain.with_domain_id(
-        subtype="Domain",
-        domain_id=domain_id,
-        fullname="PYTHON_ARITHMETIC",
-        description="ALL ABOUT ARITHMETIC IN PYTHON",
-        classification="UNCLASSIFIED",
-    )
-
-
-def test_sqlite_roundtrip(tmp_path):
+def test_sqlite_roundtrip(tmp_path, sample_domain):
     db_path = tmp_path / "domains.db"
     conn = sqlite3.connect(db_path)
@@ -21,11 +11,10 @@
     backend = SQLiteEntityBackend(Domain, conn, table_name="domains")
 
-    dom = make_domain()
-    backend.save(dom)
+    backend.save(sample_domain.to_dict())
 
-    loaded = backend.load(dom.flexo_id)
-    assert loaded.to_dict() == dom.to_dict()
+    loaded = backend.load(sample_domain.flexo_id)
+    assert loaded == sample_domain.to_dict()
 
     all_loaded = backend.load_all()
     assert len(all_loaded) == 1
-    assert all_loaded[0].domain_id == "PY_ARITHM"
+    assert Domain.from_dict(all_loaded[0]).domain_id == "PY_ARITHM"
