Changeset 0b4a5e6 in flexoentity


Ignore:
Timestamp:
10/19/25 14:50:53 (3 months ago)
Author:
Enrico Schwass <ennoausberlin@…>
Branches:
master
Children:
12d7663
Parents:
59342ce
Message:

remove state from hash to keep prefix unchanged

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • flexoentity/flexo_entity.py

    r59342ce r0b4a5e6  
    263263    @staticmethod
    264264    def verify_integrity(entity) -> bool:
    265         """
    266         Verify *state-aware* integrity.
    267 
    268         This method validates that the entity's stored digital signature
    269         matches a freshly recalculated one, based on the combination of:
    270 
    271             text_seed + current lifecycle state (one-letter code)
    272 
    273         Returns
    274         -------
    275         bool
    276             True if the entity's *state and content* are unchanged,
    277             False if either was altered or corrupted.
    278         """
    279         seed = canonical_seed(f"{entity.text_seed}:{entity.state.short()}")
    280         recalculated_sig = hashlib.blake2s(
    281             seed.encode("utf-8"), digest_size=8
    282         ).hexdigest().upper()
    283 
    284         return recalculated_sig == entity.flexo_id.signature
    285 
    286     @staticmethod
    287     def verify_content_integrity(entity) -> bool:
    288         """
    289         Verify *content-only* integrity (ignores lifecycle state).
    290 
    291         This method checks whether the stored entity's signature matches
    292         a fresh hash of its text seed alone. It does not include the
    293         lifecycle state in the fingerprint.
    294 
    295         Returns
    296         -------
    297         bool
    298         True if the text content has not been altered,
    299         False if it differs from the original content.
    300         """
    301         seed = canonical_seed(entity.text_seed)
    302         recalculated_sig = hashlib.blake2s(
    303             seed.encode("utf-8"), digest_size=8
    304         ).hexdigest().upper()
    305         return recalculated_sig == entity.flexo_id.signature
     265        # --- inhaltlicher (kryptographischer) Check ---
     266        # Hash ohne State, Signatur mit State
     267        hash_seed = canonical_seed(f"{entity.domain}:{entity.etype.short()}:{entity.text_seed}")
     268        sig_seed  = f"{hash_seed}:{entity.state.short()}"
     269
     270        expected_sig = hashlib.blake2s(sig_seed.encode("utf-8"), digest_size=8).hexdigest().upper()
     271        return expected_sig == entity.flexo_id.signature
    306272
    307273    def allowed_transitions(self) -> list[str]:
  • flexoentity/id_factory.py

    r59342ce r0b4a5e6  
    8989        raise RuntimeError("Too many collisions; adjust hash length or logic.")
    9090
    91     # ──────────────────────────────────────────────────────────────────────────
    9291    @staticmethod
    9392    def generate(domain: str, etype: str, estate: str, text: str,
     93             version: int = 1, enforce_unique=True):
     94        """
     95        Generate a deterministic Flex-O ID.
     96
     97        - The hash (and therefore prefix) depends only on domain, etype, and text.
     98        → Prefix stays stable across state changes.
     99        - The signature still includes the state for audit integrity.
     100        """
     101
     102        if not (1 <= version <= FlexOID.MAX_VERSION):
     103            raise ValueError(f"Version {version} exceeds limit; mark obsolete.")
     104
     105        date_part = datetime.now(timezone.utc).strftime("%y%m%d")
     106
     107        # state-independent hash seed → prefix stability
     108        hash_seed = canonical_seed(f"{domain}:{etype}:{text}")
     109        base_hash = FlexOID._blake_hash(hash_seed)
     110        unique_hash = (
     111            FlexOID._ensure_unique(base_hash, version) if enforce_unique else base_hash
     112        )
     113
     114        ver_part = f"{version:03d}{estate}"
     115        flexo_id_str = f"{domain}-{etype}{date_part}-{unique_hash}@{ver_part}"
     116
     117        # state-dependent signature → per-state integrity
     118        sig_seed = f"{hash_seed}:{estate}"
     119        signature = hashlib.blake2s(sig_seed.encode("utf-8"), digest_size=8).hexdigest().upper()
     120
     121        return FlexOID(flexo_id_str, signature)    # ──────────────────────────────────────────────────────────────────────────
     122
     123
     124    @staticmethod
     125    def generate_old(domain: str, etype: str, estate: str, text: str,
    94126                 version: int = 1, enforce_unique = True):
    95127        """
  • tests/test_persistance_integrity.py

    r59342ce r0b4a5e6  
    4040    assert not FlexoEntity.verify_integrity(loaded)
    4141
    42     # For state-aware systems, content-only integrity is *not applicable* unless regenerated
    43     # (i.e., the stored signature is not purely text-based). So we only assert the failure is detected.
    44     assert not FlexoEntity.verify_content_integrity(loaded)
    45 
    4642    assert approved_entity.flexo_id.signature == loaded.flexo_id.signature
    4743    assert approved_entity.flexo_id == loaded.flexo_id
Note: See TracChangeset for help on using the changeset viewer.