Index: flexoentity/composite_backend.py
===================================================================
--- flexoentity/composite_backend.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/composite_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -1,31 +1,32 @@
 from .persistance_backend import PersistanceBackend
 from .flexo_entity import FlexoEntity
-from .in_memory_backend import InMemoryBackend
+
 
 class CompositeBackend(PersistanceBackend):
     """
-    A backend that wraps multiple real backends.
+    Backend wrapper.
 
-    - Reads always come from the first backend (e.g., InMemoryBackend).
-    - Writes propagate to all backends.
+    Option A semantics:
+      - Reads come from the primary backend only.
+      - Writes propagate to primary and all sync backends.
+      - All backends store/return dicts.
     """
 
-    def __init__(self, authoritative_backend, sync_backends):
-        if not issubclass(authoritative_backend.entity_class, FlexoEntity):
-            raise TypeError("entity_class must be a subclass of FlexOEntity")
+    def __init__(self, authoritative_backend, sync_backends=None):
+        # Validate entity_class existence and compatibility
+        entity_class = getattr(authoritative_backend, "entity_class", None)
+        if entity_class is None:
+            raise TypeError("primary_backend must expose .entity_class")
+
+        if not issubclass(entity_class, FlexoEntity):
+            raise TypeError("entity_class must be a subclass of FlexoEntity")
+
+        super().__init__(entity_class)
 
         self._primary = authoritative_backend
+        self.sync_backends = list(sync_backends or [])
 
-        self.read_backend = InMemoryBackend(self.primary.entity_class)
-        # Default: create an in-memory backend as the primary backend
-
-        if sync_backends is None:
-            self.sync_backends = []
-        else:
-            self.sync_backends = sync_backends
-
-        # Validate all backends
         for b in self.sync_backends:
-            if b.entity_class != self.primary.entity_class:
+            if b.entity_class != self._primary.entity_class:
                 raise TypeError(
                     f"Backend {b} does not match entity_class={self.entity_class.__name__}"
@@ -34,54 +35,45 @@
     @property
     def primary(self):
-        """The backend used for all read operations."""
         return self._primary
 
-    @primary.setter
-    def primary(self, new_primary):
-        self._primary = new_primary
-
     def add_sync_backend(self, backend, clear=False):
-        """
-        Append an additional backend.
-        If clear=True, backend is wiped before syncing.
-        """
         if backend.entity_class != self.primary.entity_class:
             raise TypeError("Backend entity_class mismatch")
 
         if clear:
-            backend.delete_all()
+            backend.clear()
 
         # Sync current data into backend
-        for entity in self.primary.load_all():
-            backend.save(entity)
+        for d in self.primary.load_all():
+            backend.save(d)
 
         self.sync_backends.append(backend)
 
     def remove_backend(self, backend):
-        """
-        Remove a backend. Primary backend cannot be removed.
-        """
         if backend is self.primary:
             raise ValueError("Cannot remove the primary backend")
         self.sync_backends.remove(backend)
+
     # ---------------------------------------------------------
-    # Write operations propagate to *all* backends
+    # Write operations propagate to *all* backends (dicts)
     # ---------------------------------------------------------
 
-    def save(self, entity):
-        self.primary.save(entity)
+    def save(self, entity_dict: dict):
+        self.primary.save(entity_dict)
         for b in self.sync_backends:
-            b.save(entity)
+            b.save(entity_dict)
 
-    def update(self, entity):
+    def update(self, entity_dict: dict):
+        self.primary.update(entity_dict)
         for b in self.sync_backends:
-            b.update(entity)
+            b.update(entity_dict)
 
     def delete(self, flexo_id: str):
+        self.primary.delete(flexo_id)
         for b in self.sync_backends:
             b.delete(flexo_id)
 
     # ---------------------------------------------------------
-    # Read operations use only the *primary* backend
+    # Read operations from primary only
     # ---------------------------------------------------------
 
@@ -93,25 +85,26 @@
 
     # ---------------------------------------------------------
-    # Optional: flush from primary backend to all others
+    # Sync helpers
     # ---------------------------------------------------------
 
-    def sync_all(self):
+    def sync_all(self, clear_targets=False):
         """
-        Push all data from the primary backend to the other backends.
-        Useful if secondary backends were empty initially.
+        Push all data from primary backend to the other backends.
+        If clear_targets=True, wipe sync backends first.
         """
-        for entity in primary.load_all():
+        if clear_targets:
             for b in self.sync_backends:
-                b.save(entity)
+                b.clear()
+
+        for d in self.primary.load_all():
+            for b in self.sync_backends:
+                b.save(d)
 
     def clear(self):
         self.primary.clear()
         for b in self.sync_backends:
-            if hasattr(b, "clear"):
-                b.clear()
-
-    # ---------------------------------------------------------
+            b.clear()
 
     def __repr__(self):
         names = ", ".join(b.__class__.__name__ for b in self.sync_backends)
-        return f"<CompositeBackend [{names}]>"
+        return f"<CompositeBackend primary={self.primary.__class__.__name__} sync=[{names}]>"
Index: flexoentity/domain.py
===================================================================
--- flexoentity/domain.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/domain.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -1,18 +1,23 @@
-from dataclasses import dataclass
 from flexoentity import FlexoEntity, EntityType
 
-
-@dataclass
 class Domain(FlexoEntity):
-    """
-    I am a helper class to provide more information than just a
-    domain abbreviation in FlexOID, doing mapping and management
-    """
 
     ENTITY_TYPE = EntityType.DOMAIN
 
-    fullname: str = ""
-    description: str = ""
-    classification: str = "UNCLASSIFIED"
+    def __init__(self, *, flexo_id, fullname="", description="", subtype=None, fingerprint=None,
+                 classification="UNCLASSIFIED", origin=None, originator_id=None, owner_id=None,):
+
+        self.fullname = fullname
+        self.description = description
+        self.classification = classification
+
+        super().__init__(
+            flexo_id=flexo_id,
+            subtype=subtype,
+            fingerprint=fingerprint,
+            origin=origin,
+            originator_id=originator_id,
+            owner_id=owner_id,
+        )
 
     @classmethod
Index: flexoentity/entity_manager.py
===================================================================
--- flexoentity/entity_manager.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/entity_manager.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -17,12 +17,9 @@
 class EntityManager:
     """
-    Backend-agnostic manager for any FlexOEntity subclass.
+    Backend-agnostic manager for any FlexoEntity subclass.
 
-    Responsibilities:
-      - enforce ENTITY_CLASS (e.g., FlexoUser, Domain, Question)
-      - convert entities <-> dicts
-      - delegate persistence to backend
-      - provide a consistent CRUD API for GUIs and CLI
-      - avoid backend-specific code in subclasses
+    Option A contract:
+      - backends store/return dicts only
+      - manager converts dict <-> entity
     """
 
@@ -34,17 +31,40 @@
 
         if not issubclass(self.ENTITY_CLASS, FlexoEntity):
-            raise TypeError("ENTITY_CLASS must be a subclass of FlexOEntity")
+            raise TypeError("ENTITY_CLASS must be a subclass of FlexoEntity")
+
         self.local_backend = local_backend
         self.staging_backend = staging_backend
         self.permanent_backend = permanent_backend
 
+    # ------------------------------------------------------------------
+    # Conversion helpers
+    # ------------------------------------------------------------------
+
+    def _to_dict(self, entity) -> dict:
+        self._ensure_type(entity)
+        return entity.to_dict()
+
+    def _to_entity(self, entity_dict: dict):
+        if entity_dict is None:
+            return None
+        return self.ENTITY_CLASS.from_dict(entity_dict)
+
+    def _to_entities(self, dicts: list[dict]):
+        return [self._to_entity(d) for d in dicts]
+
+    # ------------------------------------------------------------------
+    # Locators
+    # ------------------------------------------------------------------
+
     def backend_of_domain_id(self, domain_id: str):
+        # Note: this converts dict->entity because domain_id is a FlexoEntity property
         for backend_name, backend in [
-                ("local", self.local_backend),
-                ("staging", self.staging_backend),
-                ("permanent", self.permanent_backend),
+            ("local", self.local_backend),
+            ("staging", self.staging_backend),
+            ("permanent", self.permanent_backend),
         ]:
-            for dom in backend.load_all():
-                if dom.domain_id == domain_id:
+            for d in backend.load_all():
+                e = self._to_entity(d)
+                if e.domain_id == domain_id:
                     return backend_name
         return None
@@ -52,7 +72,7 @@
     def backend_of_flexo_id(self, flexo_id: str):
         for backend_name, backend in [
-                ("local", self.local_backend),
-                ("staging", self.staging_backend),
-                ("permanent", self.permanent_backend),
+            ("local", self.local_backend),
+            ("staging", self.staging_backend),
+            ("permanent", self.permanent_backend),
         ]:
             if backend.load(flexo_id) is not None:
@@ -61,61 +81,60 @@
 
     # ------------------------------------------------------------------
-    # CRUD operations
+    # CRUD operations (entity API)
     # ------------------------------------------------------------------
 
     def add(self, entity):
-        """Insert a new entity."""
-        self._ensure_type(entity)
-        self.local_backend.save(entity)
+        self.local_backend.save(self._to_dict(entity))
 
     def update(self, entity):
-        """Replace an existing entity (same flexo_id)."""
-        self._ensure_type(entity)
-        self.local_backend.update(entity)
+        self.local_backend.update(self._to_dict(entity))
 
     def delete(self, flexo_id: str):
-        """Remove entity by string flexo_id."""
         self.local_backend.delete(flexo_id)
 
     # ------------------------------------------------------------------
-    # Retrieval
+    # Retrieval (entity API)
     # ------------------------------------------------------------------
 
     def get(self, flexo_id: str):
-        """
-        Load entity by flexo_id str.
-        Returns ENTITY_CLASS instance or None.
-        """
-        return self.local_backend.load(flexo_id)
+        d = self.local_backend.load(flexo_id)
+        return self._to_entity(d)
 
     # FIXME: Readd staging backend later
     def all(self):
-        """Load all entities as a list of instances."""
-        return (self.local_backend.load_all() + # self.staging_backend.load_all() +
-                self.permanent_backend.load_all())
+        dicts = (
+            self.local_backend.load_all()
+            # + self.staging_backend.load_all()
+            + self.permanent_backend.load_all()
+        )
+        return self._to_entities(dicts)
 
     def promote_to_staging(self, flexo_id):
-        entity = self.local_backend.load(flexo_id)
-        if entity is None:
-            raise EntityNotFoundError
-        self.staging_backend.save(entity)
+        d = self.local_backend.load(flexo_id)
+        if d is None:
+            raise EntityNotFoundError(flexo_id)
+        self.staging_backend.save(d)
         self.local_backend.delete(flexo_id)
 
     def promote_to_permanent(self, flexo_id):
-        entity = self.staging_backend.load(flexo_id)
-        if entity is None:
-            raise EntityNotFoundError
-        self.permanent_backend.save(entity)
+        d = self.staging_backend.load(flexo_id)
+        if d is None:
+            raise EntityNotFoundError(flexo_id)
+        self.permanent_backend.save(d)
         self.staging_backend.delete(flexo_id)
 
     def sync_all(self):
         # sync staging → local
-        for e in self.staging_backend.load_all():
-            self.local_backend.save(e)
+        for d in self.staging_backend.load_all():
+            self.local_backend.save(d)
 
         # sync permanent → local
-        for e in self.permanent_backend.load_all():
-            self.local_backend.save(e)
-        self.refresh()
+        for d in self.permanent_backend.load_all():
+            self.local_backend.save(d)
+
+        # NOTE: refresh() is not defined here.
+        # If you want a hook, define it explicitly, otherwise remove this call.
+        if hasattr(self, "refresh"):
+            self.refresh()
 
     # ------------------------------------------------------------------
@@ -124,5 +143,5 @@
 
     def exists(self, flexo_id: str) -> bool:
-        return self.get(flexo_id) is not None
+        return self.local_backend.load(flexo_id) is not None
 
     def count(self) -> int:
@@ -130,9 +149,6 @@
 
     def add_or_update(self, entity):
-        """
-        Convenience for GUIs:
-        Insert or overwrite based on whether flexo_id exists.
-        """
-        if self.exists(entity.flexo_id):
+        fid = str(entity.flexo_id)
+        if self.exists(fid):
             self.update(entity)
         else:
@@ -140,5 +156,6 @@
 
     def as_collection(self):
-        return TypedCollection(self.ENTITY_CLASS, items=self.local_backend.load_all())
+        # Collection expects entities (your current TypedCollection usage suggests this)
+        return TypedCollection(self.ENTITY_CLASS, items=self.all())
 
     # ------------------------------------------------------------------
@@ -149,10 +166,7 @@
         if not isinstance(entity, self.ENTITY_CLASS):
             raise TypeError(
-                f"Expected {self.ENTITY_CLASS.__name__}, "
-                f"got {type(entity).__name__}"
+                f"Expected {self.ENTITY_CLASS.__name__}, got {type(entity).__name__}"
             )
 
-    # ------------------------------------------------------------------
-
     def __repr__(self):
-        return f"<FlexoEntityManager for {self.ENTITY_CLASS.__name__}>"
+        return f"<EntityManager for {self.ENTITY_CLASS.__name__}>"
Index: flexoentity/flexo_entity.py
===================================================================
--- flexoentity/flexo_entity.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/flexo_entity.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -129,5 +129,4 @@
 
 
-@dataclass()
 class FlexoEntity(ABC):
     """
@@ -160,11 +159,4 @@
     I am the living, editable layer that connects identity with accountability.
     """
-    _in_factory: bool = field(default=False, repr=False)
-    subtype: str = ""
-    flexo_id: Optional[FlexOID] = field(default=None)
-    fingerprint: str = field(default_factory=str)
-    originator_id: UUID = field(default=UUID(int=0))
-    owner_id: UUID = field(default=UUID(int=0))
-    origin: Optional[str] = field(default=None)
 
     def with_new_owner(self, new_owner: UUID):
@@ -174,4 +166,17 @@
         return copy
 
+    def __init__(self, *, flexo_id, subtype=None, fingerprint=None,
+                 origin=None, originator_id=None, owner_id=None):
+
+        if flexo_id is None:
+            raise ValueError("flexo_id must be provided")
+
+        self.flexo_id = flexo_id
+        self.subtype = subtype or self.__class__.__name__
+        self.origin = origin
+        self.originator_id = originator_id
+        self.owner_id = owner_id
+        self.fingerprint = fingerprint or self._compute_fingerprint()
+
     @staticmethod
     def canonicalize_content_dict(data) -> str:
@@ -183,4 +188,12 @@
         """
         return json.dumps(data, sort_keys=True, separators=(",", ":"))
+
+    def __eq__(self, other):
+        if not isinstance(other, FlexoEntity):
+            return NotImplemented
+        return self.flexo_id == other.flexo_id
+
+    def __hash__(self):
+        return hash(self.flexo_id)
 
     @property
@@ -211,41 +224,22 @@
         raise NotImplementedError("Subclasses must implement default()")
 
+
     @classmethod
     def with_domain_id(cls, domain_id: str, **kwargs):
-        # from .domain_manager import DomainManager
         entity_type = getattr(cls, "ENTITY_TYPE", None)
         if not entity_type:
             raise ValueError(f"{cls.__name__} must define ENTITY_TYPE")
 
-        flexo_id = FlexOID.safe_generate(
+        oid = FlexOID.safe_generate(
             domain_id=domain_id,
             entity_type=entity_type.value,
             state=EntityState.DRAFT.value,
-            text=kwargs.get("text_seed", ""),
+            text="",
             version=1,
         )
 
-        obj = cls(flexo_id=flexo_id, _in_factory=True, **kwargs)
+        obj = cls(flexo_id=oid, **kwargs)
         obj.fingerprint = obj._compute_fingerprint()
         return obj
-
-    def __post_init__(self):
-        if not self._in_factory:
-            raise RuntimeError(
-                f"{self.__class__.__name__} must be created via "
-                f"with_domain_id() or from_dict()."
-            )
-
-        if not self.flexo_id:
-            raise RuntimeError(
-                f"{self.__class__.__name__} created without flexo_id. "
-                f"Factory must assign it before __post_init__."
-            )
-
-        if not self.fingerprint:
-            self.fingerprint = self._compute_fingerprint()
-
-        if not self.subtype:
-            self.subtype = self.__class__.__name__
 
     def __str__(self):
@@ -279,55 +273,21 @@
 
     @classmethod
-    def from_dict(cls, data):
-        """
-        FINAL VERSION:
-        - NEVER generates a new FlexOID.
-        - NEVER calls with_domain().
-        - ALWAYS restores the canonical Domain via DomainManager.
-        """
-        meta = data.get("meta", "")
-
-        if not meta:
-            raise ValueError("Serialized entity must include 'meta' object.")
-
-        schema = meta.get("schema", {"name": "flexograder-entity",
-                                     "version": "1.0"})
-        name = schema.get("name")
-        version = schema.get("version")
-
-        if name != SCHEMA_NAME:
-            raise ValueError(f"Unsupported schema name: {name}")
-
-        if version != SCHEMA_VERSION:
-            raise ValueError(
-                f"Unsupported schema version {version}, expected {SCHEMA_VERSION}"
-            )
-
-        flexo_id = FlexOID(meta.get("flexo_id"))
-        subtype = meta.get("subtype")
-        if not subtype:
-            raise ValueError("Serialized entity must include 'subtype'.")
-
-        try:
-            owner_id = UUID(meta.get("owner_id"))
-        except ValueError as e:
-            logger.warning(f"Missing or wrong owner_id {e}")
-            owner_id = UUID(int=0)
-        try:
-            originator_id = UUID(meta.get("originator_id"))
-        except ValueError as e:
-            logger.warning(f"Missing or wrong originator_id {e}")
-            originator_id = UUID(int=0)
+    def from_dict(cls, data: dict):
+        meta = data["meta"]
+        content = data["content"]
+
+        flexo_id = FlexOID(meta["flexo_id"])
 
         obj = cls(
             flexo_id=flexo_id,
-            subtype=subtype,
-            origin=meta.get("origin", ""),
-            fingerprint=meta.get("fingerprint", ""),
-            owner_id=owner_id,
-            originator_id=originator_id,
-            _in_factory=True
+            subtype=meta.get("subtype"),
+            fingerprint=meta.get("fingerprint"),
+            origin=meta.get("origin"),
+            originator_id=meta.get("originator_id"),
+            owner_id=meta.get("owner_id"),
         )
-        obj._deserialize_content(data.get("content", {}))
+
+        obj._deserialize_content(content)
+
         return obj
 
@@ -472,5 +432,5 @@
         old_id = self.flexo_id
         self.flexo_id = self.flexo_id.with_state(EntityState.APPROVED_AND_SIGNED.value)
-        self.flexo_id.origin = old_id
+        self.origin = old_id
         return self
 
Index: flexoentity/flexo_signature.py
===================================================================
--- flexoentity/flexo_signature.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/flexo_signature.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -56,40 +56,51 @@
 
 
-@dataclass
 class FlexoSignature(FlexoEntity):
-    """
-    I represent a digital or procedural signature for another entity.
-
-    This is a stub version: I only carry logical metadata, not cryptographic proof.
-    Later, platform-specific implementations (e.g. Windows certificate signing)
-    can fill the 'signature_data' field with real data.
-
-    Lifecycle:
-      - Created in DRAFT → becomes APPROVED once verified
-      - Optionally moves to PUBLISHED if distributed externally
-    """
     ENTITY_TYPE = EntityType.ATTESTATION
 
-    signed_entity: Optional[FlexOID] = None
-    signer_id: Optional[UUID] = None
+    def __init__(
+        self,
+        *,
+        flexo_id,
+        signed_entity: Optional[FlexOID] = None,
+        signer_id: Optional[UUID] = None,
+        signature_data: str = "",
+        signature_type: str = "PKCS7-DER",
+        certificate_reference: CertificateReference | None = None,
+        certificate_thumbprint: str = "",
+        comment: Optional[str] = None,
+        subtype=None,
+        fingerprint=None,
+        origin=None,
+        originator_id=None,
+        owner_id=None,
+    ):
+        # content fields
+        self.signed_entity = signed_entity
+        self.signer_id = signer_id
+        self.signature_data = signature_data
+        self.signature_type = signature_type
+        self.certificate_reference = certificate_reference
+        self.certificate_thumbprint = certificate_thumbprint
+        self.comment = comment
 
-    # PKCS#7 DER, base64-encoded
-    signature_data: str = ""
-    signature_type: str = "PKCS7-DER"
-
-    certificate_reference: CertificateReference | None = None
-    certificate_thumbprint: str = ""
-
-    comment: Optional[str] = None
+        # meta fields
+        super().__init__(
+            flexo_id=flexo_id,
+            subtype=subtype,
+            fingerprint=fingerprint,
+            origin=origin,
+            originator_id=originator_id,
+            owner_id=owner_id,
+        )
 
     def _serialize_content(self):
         return {
-            "signed_entity": str(self.signed_entity),
-            "signer_id": str(self.signer_id),
+            "signed_entity": str(self.signed_entity) if self.signed_entity else None,
+            "signer_id": str(self.signer_id) if self.signer_id else None,
             "signature_data": self.signature_data,
             "signature_type": self.signature_type,
-            # "certificate_reference": self.certificate_reference.to_dict(),
             "certificate_thumbprint": self.certificate_thumbprint,
-            "comment": self.comment
+            "comment": self.comment,
         }
 
@@ -100,10 +111,14 @@
     @classmethod
     def default(cls):
-        """Required by FlexoEntity. Returns an empty draft signature."""
-        return cls()
+        """
+        Required by FlexoEntity.
+        Returns an empty draft signature.
+        """
+        return cls.with_domain_id(domain_id="GEN")
 
     @classmethod
     def create_signed(cls, data: bytes, entity: FlexOID, signer_id: UUID, backend):
         sig = backend.sign(data)
+
         return cls.with_domain_id(
             domain_id=entity.domain_id,
@@ -112,5 +127,5 @@
             signature_data=base64.b64encode(sig).decode(),
             certificate_reference=backend.cert_ref,
-            certificate_thumbprint=backend.certificate_thumbprint
+            certificate_thumbprint=backend.certificate_thumbprint,
         )
 
@@ -118,3 +133,2 @@
         raw = base64.b64decode(self.signature_data)
         return backend.verify(data, raw)
-
Index: flexoentity/id_factory.py
===================================================================
--- flexoentity/id_factory.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/id_factory.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -17,5 +17,5 @@
     ENTITY_TYPE — a compact entity type single letter code (e.g., "I" for ITEM)
     YYMMDD      — the UTC creation date
-    HASH        — a 12-hex BLAKE2s digest derived from canonical content
+    HASH        — a random cryptographic nonce ensuring global uniqueness
     VERSION     — a three-digit lineage counter (001-999)
     STATE       — a single capital letter indicating lifecycle state
@@ -28,7 +28,7 @@
 
 • Draft → Approved:
-      I generate a fully new FlexOID whose hash and version reflect
-      the new, stable content.  This step marks the transition from
-      provisional to permanent identity.  No extra version bump is required.
+      I generate a fully new FlexOID
+      This step marks the transition from provisional to permanent identity.
+      No extra version bump is required.
 
 • Approved → Signed → Published → Obsolete:
@@ -144,5 +144,5 @@
 
         version_int = int(version)
-        if not (1 <= version_int <= cls.MAX_VERSION):
+        if not 1 <= version_int <= cls.MAX_VERSION:
             raise ValueError(f"Version {version} out of range.")
 
@@ -255,13 +255,13 @@
 
     @staticmethod
-    def generate(domain: str, entity_type: str, state: str, text: str, version: int = 1):
-        """
-        I create a new deterministic Flex-O ID.
-
-        I combine the domain, entity type, and canonicalized *text*
-        into a stable BLAKE2s hash.  My prefix therefore remains
-        unchanged when only the state or version changes.
-        """
-        if not (1 <= version <= FlexOID.MAX_VERSION):
+    def generate(domain: str, entity_type: str, state: str, text: str = "", version: int = 1):
+        """
+        I create a new Flex-O ID.
+        
+        Identity is independent from content.
+        The hash part is now a cryptographic random nonce.
+        """
+
+        if not 1 <= version <= FlexOID.MAX_VERSION:
             raise ValueError(f"Version {version} exceeds limit; mark obsolete.")
 
@@ -270,41 +270,24 @@
 
         date_part = datetime.now(timezone.utc).strftime("%y%m%d")
-        hash_seed = canonical_seed(f"{domain}:{entity_type}:{canonical_seed(text)}")
-        base_hash = FlexOID._blake_hash(hash_seed)
-        return FlexOID(f"{domain}-{entity_type}{date_part}-{base_hash}@{version:03d}{state}")
+
+        # 12 hex characters = 48-bit nonce (same visible size as before)
+        nonce = secrets.token_hex(6).upper()
+
+        return FlexOID(f"{domain}-{entity_type}{date_part}-{nonce}@{version:03d}{state}")
 
     @staticmethod
-    def safe_generate(domain_id, entity_type, state, text, version=1, repo=None):
-        """
-        I create a new deterministic ID like `generate`,
-        but I also consult an optional *repo* to avoid hash collisions.
-
-        If a different seed has already produced the same prefix,
-        I deterministically salt my seed and regenerate a unique ID.
-        """
-        oid = FlexOID.generate(domain_id, entity_type, state, text, version=version)
+    def safe_generate(domain_id, entity_type, state, text="", version=1, repo=None):
+        """
+        Generate a random identity and retry only if it already exists in repo.
+        """
 
         if repo is None:
-            return oid
-
-        existing = repo.get(str(oid)) if hasattr(repo, "get") else repo.get(oid)
-        if not existing:
-            return oid
-
-        try:
-            same_seed = (
-                getattr(existing, "text_seed", None) == text
-                or getattr(existing, "canonical_seed", lambda: None)() == canonical_seed(text)
-            )
-        except Exception:
-            same_seed = False
-
-        if same_seed:
-            return oid
-
-        logger.warning(f"FlexOID collision detected for {oid}")
-        salt = secrets.token_hex(1)
-        salted_text = f"{text}|salt:{salt}"
-        return FlexOID.generate(domain_id, entity_type, state, salted_text, version=version)
+            return FlexOID.generate(domain_id, entity_type, state, text="", version=version)
+
+        while True:
+            oid = FlexOID.generate(domain_id, entity_type, state, text="", version=version)
+            existing = repo.get(str(oid)) if hasattr(repo, "get") else repo.get(oid)
+            if not existing:
+                return oid
 
     @classmethod
Index: flexoentity/in_memory_backend.py
===================================================================
--- flexoentity/in_memory_backend.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/in_memory_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -1,4 +1,3 @@
 import json
-from .flexo_entity import FlexoEntity
 from .persistance_backend import PersistanceBackend
 
@@ -6,30 +5,17 @@
 class InMemoryBackend(PersistanceBackend):
     """
-    Persistence backend for a *typed* collection of FlexOEntities.
-
-    - Stores dicts internally (no entities)
-    - Reconstructs entities using ENTITY_CLASS.from_dict() on load
-    - Accepts entity_class injected at construction time
+    Persistence backend storing and returning dicts only (Option A).
     """
 
     def __init__(self, entity_class, storage=None):
-        if not issubclass(entity_class, FlexoEntity):
-            raise TypeError("entity_class must be a subclass of FlexOEntity")
-
-        super().__init__(entity_class = entity_class)
+        super().__init__(entity_class=entity_class)
         self._storage = storage if storage is not None else {}
 
-    # ---------------------------------------------------------
-    # Core persistence API (dict-based internally)
-    # ---------------------------------------------------------
+    def save(self, entity_dict: dict):
+        flexo_id = entity_dict["meta"]["flexo_id"]
+        self._storage[flexo_id] = entity_dict
 
-    def save(self, entity):
-        """Store serialized entity dict by flexo_id."""
-        data = entity.to_dict()
-        flexo_id = data["meta"]["flexo_id"]
-        self._storage[flexo_id] = data
-
-    def update(self, entity):
-        self.save(entity)
+    def update(self, entity_dict: dict):
+        self.save(entity_dict)
 
     def delete(self, flexo_id: str):
@@ -37,34 +23,19 @@
 
     def load(self, flexo_id: str):
-        """Return an entity instance or None."""
-        d = self._storage.get(flexo_id)
-        return None if d is None else self.entity_class.from_dict(d)
+        return self._storage.get(flexo_id)
 
     def load_all(self):
-        """Return a list of entity instances."""
-        return [
-            self.entity_class.from_dict(d)
-            for d in self._storage.values()
-        ]
+        return list(self._storage.values())
 
     def clear(self):
         self._storage.clear()
 
-    # ---------------------------------------------------------
-    # Optional: JSON file persistence
-    # ---------------------------------------------------------
-
+    # Optional file helpers still fine (dicts in/out)
     def save_to_file(self, path):
         with open(path, "w", encoding="utf-8") as f:
-            json.dump(
-                list(self._storage.values()),
-                f,
-                ensure_ascii=False,
-                indent=2
-            )
+            json.dump(list(self._storage.values()), f, ensure_ascii=False, indent=2)
 
     def load_from_file(self, path):
         with open(path, "r", encoding="utf-8") as f:
             data = json.load(f)
-        # Replace storage with file content
         self._storage = {d["meta"]["flexo_id"]: d for d in data}
Index: flexoentity/json_file_backend.py
===================================================================
--- flexoentity/json_file_backend.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/json_file_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -9,21 +9,19 @@
 
     Uses an internal InMemoryBackend and syncs to a single JSON file on disk.
+    Dict-only contract (Option A).
     """
 
     def __init__(self, entity_class, path):
+        super().__init__(entity_class=entity_class)
         self._mem = InMemoryBackend(entity_class)
         self._path = path
 
-    @property
-    def entity_class(self):
-        return self._mem.entity_class
+    # core API delegates (dicts)
 
-    # core API just delegates to memory backend
+    def save(self, entity_dict: dict):
+        self._mem.save(entity_dict)
 
-    def save(self, entity):
-        self._mem.save(entity)
-
-    def update(self, entity):
-        self._mem.update(entity)
+    def update(self, entity_dict: dict):
+        self._mem.update(entity_dict)
 
     def delete(self, flexo_id: str):
@@ -39,8 +37,8 @@
         self._mem.clear()
 
-    # file sync
+    # file sync (dicts)
 
     def flush_to_file(self):
-        data = [e.to_dict() for e in self._mem.load_all()]
+        data = self._mem.load_all()
         with open(self._path, "w", encoding="utf-8") as f:
             json.dump(data, f, ensure_ascii=False, indent=2)
@@ -55,3 +53,3 @@
         self._mem.clear()
         for d in data:
-            self._mem.save(self.entity_class.from_dict(d))
+            self._mem.save(d)
Index: flexoentity/persistance_backend.py
===================================================================
--- flexoentity/persistance_backend.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/persistance_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -3,5 +3,13 @@
     Interface for all persistence backends.
 
-    Stores serialized FlexOEntity dicts with a flexo_id key.
+    Contract (Option A):
+      - Backends store serialized entity dictionaries.
+      - Backends return dictionaries (never FlexoEntity instances).
+      - EntityManager is responsible for dict <-> entity conversion.
+
+    Stored dict format must include:
+      - meta.flexo_id (string)
+      - meta.schema.name / meta.schema.version
+      - content (entity-specific)
     """
 
@@ -17,12 +25,20 @@
         self._entity_class = a_class
 
-    def save(self, flexo_entity) -> None:
+    # -------------------------
+    # Write API (dict)
+    # -------------------------
+
+    def save(self, entity_dict: dict) -> None:
         raise NotImplementedError
 
-    def update(self, flexo_entity) -> None:
+    def update(self, entity_dict: dict) -> None:
         raise NotImplementedError
 
     def delete(self, flexo_id: str) -> None:
         raise NotImplementedError
+
+    # -------------------------
+    # Read API (dict)
+    # -------------------------
 
     def load(self, flexo_id: str) -> dict | None:
Index: flexoentity/runtime_backend.py
===================================================================
--- flexoentity/runtime_backend.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/runtime_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -1,28 +1,22 @@
 from .persistance_backend import PersistanceBackend
-from .flexo_entity import FlexoEntity
 
 
 class RuntimeBackend(PersistanceBackend):
     """
-    Runtime backend.
+    Runtime backend (Option A).
 
-    - Stores entity *instances*
-    - Guarantees identity stability
-    - No serialization
-    - No reconstruction
+    - Stores dicts only (no entity instances)
+    - Useful as an in-process cache
     """
 
     def __init__(self, entity_class):
-        if not issubclass(entity_class, FlexoEntity):
-            raise TypeError("entity_class must be a subclass of FlexoEntity")
+        super().__init__(entity_class=entity_class)
+        self._store: dict[str, dict] = {}
 
-        super().__init__(entity_class=entity_class)
-        self._store: dict[str, FlexoEntity] = {}
+    def save(self, entity_dict: dict):
+        self._store[entity_dict["meta"]["flexo_id"]] = entity_dict
 
-    def save(self, entity):
-        self._store[entity.flexo_id] = entity
-
-    def update(self, entity):
-        self._store[entity.flexo_id] = entity
+    def update(self, entity_dict: dict):
+        self.save(entity_dict)
 
     def delete(self, flexo_id: str):
Index: flexoentity/sqlite_entity_backend.py
===================================================================
--- flexoentity/sqlite_entity_backend.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ flexoentity/sqlite_entity_backend.py	(revision 3389960f311b160942ab625deddd67b7315c75ea)
@@ -5,15 +5,16 @@
 class SQLiteEntityBackend(PersistanceBackend):
     """
-    SQLite backend storing **dicts**, not entities.
-    Managers do the entity conversions.
+    SQLite backend storing and returning **dicts only**.
+
+    Note:
+      - EntityManager performs dict <-> entity conversion.
+      - This backend does not call entity_class.from_dict().
     """
 
     def __init__(self, entity_class, conn, table_name):
         super().__init__(entity_class)
-        self.entity_class = entity_class
         self.conn = conn
         self.table = table_name
         self._init_schema()
-
 
     def _init_schema(self):
@@ -26,19 +27,45 @@
         self.conn.commit()
 
-    def save(self, entity):
-        entity_dict = entity.to_dict()
-        fid = entity_dict["meta"]["flexo_id"]
+    # -------------------------
+    # Helpers
+    # -------------------------
+
+    def _ensure_dict(self, entity_or_dict) -> dict:
+        """
+        Transitional helper:
+          - Accept dict (preferred)
+          - Accept FlexoEntity-like objects with .to_dict() (legacy)
+        """
+        if isinstance(entity_or_dict, dict):
+            return entity_or_dict
+        if hasattr(entity_or_dict, "to_dict"):
+            return entity_or_dict.to_dict()
+        raise TypeError(f"Expected dict or object with to_dict(), got {type(entity_or_dict).__name__}")
+
+    def _flexo_id_from_dict(self, entity_dict: dict) -> str:
+        try:
+            return entity_dict["meta"]["flexo_id"]
+        except Exception as e:
+            raise KeyError("entity_dict must contain meta.flexo_id") from e
+
+    # -------------------------
+    # Writes (dict)
+    # -------------------------
+
+    def save(self, entity_dict):
+        d = self._ensure_dict(entity_dict)
+        fid = self._flexo_id_from_dict(d)
         self.conn.execute(
             f"INSERT OR REPLACE INTO {self.table} (flexo_id, json) VALUES (?, ?)",
-            (fid, json.dumps(entity_dict))
+            (fid, json.dumps(d))
         )
         self.conn.commit()
 
-    def update(self, entity):
-        entity_dict = entity.to_dict()
-        fid = entity_dict["meta"]["flexo_id"]
+    def update(self, entity_dict):
+        d = self._ensure_dict(entity_dict)
+        fid = self._flexo_id_from_dict(d)
         self.conn.execute(
             f"UPDATE {self.table} SET json = ? WHERE flexo_id = ?",
-            (json.dumps(entity_dict), fid)
+            (json.dumps(d), fid)
         )
         self.conn.commit()
@@ -51,4 +78,8 @@
         self.conn.commit()
 
+    # -------------------------
+    # Reads (dict)
+    # -------------------------
+
     def load(self, flexo_id):
         row = self.conn.execute(
@@ -60,5 +91,9 @@
             return None
 
-        return self.entity_class.from_dict(json.loads(row["json"]))
+        # row indexing depends on connection row_factory; support both
+        raw = row["json"] if isinstance(row, dict) or hasattr(row, "__getitem__") else row[0]
+        if not isinstance(raw, str):
+            raw = raw[0]
+        return json.loads(raw)
 
     def load_all(self):
@@ -67,5 +102,11 @@
         ).fetchall()
 
-        return [self.entity_class.from_dict(json.loads(r["json"])) for r in rows]
+        result = []
+        for r in rows:
+            raw = r["json"] if isinstance(r, dict) or hasattr(r, "__getitem__") else r[0]
+            if not isinstance(raw, str):
+                raw = raw[0]
+            result.append(json.loads(raw))
+        return result
 
     def clear(self):
Index: tests/test_composite_backend.py
===================================================================
--- tests/test_composite_backend.py	(revision 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ 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 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ 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 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ 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 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ 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 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ 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 54941b4a9b58ed1a2e94d9a1b253bbb291dfcdac)
+++ 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"
