Index: tests/conftest.py
===================================================================
--- tests/conftest.py	(revision 8aa20c772729e2042bc331b986df06947d18fcdd)
+++ tests/conftest.py	(revision 5c72356eddc16f354a461320a48eaf1e34225257)
@@ -4,5 +4,5 @@
 from dataclasses import dataclass, field
 from typing import List
-from flexoentity import FlexoEntity, EntityType, EntityState, Domain
+from flexoentity import FlexOID, FlexoEntity, EntityType, EntityState, Domain
 
 @pytest.fixture
@@ -37,14 +37,26 @@
 class SingleChoiceQuestion(FlexoEntity):
     """A minimal stub to test FlexoEntity integration."""
+    ENTITY_TYPE = EntityType.ITEM
+
     text: str = ""
     options: List[AnswerOption] = field(default_factory=list)
 
+    def __post_init__(self):
+        # If no FlexOID yet, generate a draft ID now.
+        if not getattr(self, "flexo_id", None):
+            domain_code = (
+                self.domain.domain if isinstance(self.domain, Domain) else "GEN"
+            )
+            self.flexo_id = FlexOID.safe_generate(
+                domain=domain_code,
+                entity_type=EntityType.ITEM.value,     # 'I'
+                estate=EntityState.DRAFT.value,        # 'D'
+                text=self.text_seed or self.text,
+                version=1,
+            )
 
     @classmethod
     def default(cls):
-        return cls(domain=Domain(domain="GEN",
-                                 entity_type=EntityType.DOMAIN,
-                                 state=EntityState.DRAFT),
-                   state=EntityState.DRAFT, entity_type=EntityType.ITEM)
+        return cls(domain=Domain(domain="GEN"))
 
     def to_dict(self):
@@ -68,5 +80,5 @@
     @classmethod
     def from_dict(cls, data):
-        obj = cls(
+        obj = cls(domain=Domain(domain="GEN"),
             text=data.get("text", ""),
             options=[AnswerOption.from_dict(o) for o in data.get("options", [])],
@@ -74,8 +86,5 @@
         # restore FlexoEntity core fields
         obj.domain = data.get("domain")
-        obj.entity_type = EntityType[data.get("etype")] if "etype" in data else EntityType.ITEM
-        obj.state = EntityState[data.get("state")] if "state" in data else EntityState.DRAFT
         if "flexo_id" in data:
-            from flexoentity import FlexOID
             obj.flexo_id = FlexOID.parsed(data["flexo_id"])
         return obj
@@ -87,7 +96,7 @@
 @pytest.fixture
 def sample_question():
-    return SingleChoiceQuestion(domain=Domain.default(),
-                               text="What is 2 + 2?",
-                               options=[],
-                               entity_type=EntityType.ITEM,
-                               state=EntityState.DRAFT)
+    q = SingleChoiceQuestion(domain=Domain.default(),
+                             text="What is 2 + 2?",
+                             options=[])
+    q._update_fingerprint()
+    return q
Index: tests/test_id_lifecycle.py
===================================================================
--- tests/test_id_lifecycle.py	(revision 8aa20c772729e2042bc331b986df06947d18fcdd)
+++ tests/test_id_lifecycle.py	(revision 5c72356eddc16f354a461320a48eaf1e34225257)
@@ -20,15 +20,24 @@
     assert q.flexo_id.version == 1
 
-
-def test_signing_bumps_version(sample_question):
+def test_signing_does_not_bump_version(sample_question):
     q = sample_question
     q.approve()
-    v_before = str(q.flexo_id)
+    before = q.flexo_id
     q.sign()
+    after = q.flexo_id
+
+    # state changed
     assert q.state == EntityState.APPROVED_AND_SIGNED
-    assert str(q.flexo_id) != v_before
+
+    # version unchanged
+    assert before.version == after.version
+
+    # only suffix letter differs
+    assert before.prefix == after.prefix
+    assert before.state_code == "A"
+    assert after.state_code == "S"
 
 
-def test_publish_bumps_version(sample_question):
+def test_publish_does_not_bump_version(sample_question):
     q = sample_question
     q.approve()
@@ -37,5 +46,5 @@
     q.publish()
     assert q.state == EntityState.PUBLISHED
-    assert q.flexo_id.version == v_before + 1
+    assert q.flexo_id.version == v_before
 
 
@@ -70,4 +79,5 @@
     # simulate tampering
     q.text = "Tampered text"
+    print(FlexoEntity.debug_integrity(q))
     assert not FlexoEntity.verify_integrity(q)
 
@@ -112,4 +122,6 @@
     for _ in range(FlexOID.MAX_VERSION - 1):
         q.bump_version()
+
+    # Next one must raise
     with pytest.raises(RuntimeError, match="mark obsolete"):
-        q.sign()
+        q.bump_version()
Index: tests/test_id_stress.py
===================================================================
--- tests/test_id_stress.py	(revision 8aa20c772729e2042bc331b986df06947d18fcdd)
+++ tests/test_id_stress.py	(revision 5c72356eddc16f354a461320a48eaf1e34225257)
@@ -82,21 +82,4 @@
 
 
-def test_version_ceiling_enforcement(sample_question):
-    """Simulate approaching @999 to trigger obsolescence guard."""
-    q = sample_question
-    q.approve()
-
-    # artificially bump version number to near ceiling
-    q.flexo_id = FlexOID.from_oid_and_version(q.flexo_id, 998)
-
-    # 998 → 999 is allowed
-    q.sign()
-    assert q.flexo_id.version == 999
-
-    # 999 → 1000 should raise RuntimeError
-    with pytest.raises(ValueError):
-        q.publish()
-
-
 def test_massive_lifecycle_simulation(sample_question):
     """
