- Timestamp:
- 10/20/25 14:32:42 (3 months ago)
- Branches:
- master
- Children:
- 859e2b1
- Parents:
- 8a238e2
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
README.md
r8a238e2 r3d65ce5 1 # flexoentity 2 3 **flexoentity** is the foundational Python library of the *Flex-O* ecosystem. 4 5 It provides: 6 - `FlexOID`: a deterministic, state-aware, and versioned identifier system 7 - `FlexoEntity`: a base class for reproducible, lifecycle-tracked domain entities 8 9 Together, these components ensure traceability, immutability, and auditability 10 across the Flex-O-Grader, Flex-O-Vault, and Flex-O-Drill projects. 11 12 ### Example 13 14 ```python 15 from flexoentity import FlexOID, FlexoEntity 16 17 question = FlexoEntity( 18 domain="AF", 19 etype="Q", 20 text="What is Ohm’s law?", 21 state="A" 22 ) 23 print(question.flexo_id) 24 25 Features 26 • BLAKE2s hashing (fast, stdlib, deterministic) 27 • Canonical seed generation 28 • Lifecycle state encoding (@001A) 29 • UTC-based timestamps 30 • Collision disambiguation 31 32 Licensed under the MIT License. 1 #+TITLE: flexoentity 2 #+SUBTITLE: A hardened entity base and deterministic identifier system for the Flex-O family 3 #+AUTHOR: Enno 4 #+DATE: 2025-10-20 5 #+OPTIONS: toc:3 num:nil 6 7 * Overview 8 9 `flexoentity` provides the *identity and lifecycle backbone* for all Flex-O components 10 (Flex-O-Grader, Flex-O-Vault, Flex-O-Drill, …). 11 12 It defines how entities such as questions, media, catalogs, and exams are *identified, versioned, signed, and verified* — all without any external database dependencies. 13 14 At its heart lie two modules: 15 16 - =id_factory.py= – robust, cryptographically-verifiable *Flex-O ID generator* 17 - =versioned_entity.py= – abstract *base class for all versioned entities* 18 19 Together, they form a compact yet powerful foundation for audit-ready, reproducible data structures across offline and air-gapped deployments. 20 21 ✳️ Design Goals 22 |----------------|--------------------------------------------------------------------------------------------------------| 23 | Goal | Description | 24 |----------------|--------------------------------------------------------------------------------------------------------| 25 | *Determinism* | IDs are derived from canonicalized entity content — identical input always yields identical ID prefix. | 26 | *Integrity* | BLAKE2s hashing and digital signatures protect against manual tampering. | 27 | *Traceability* | Version numbers (=@001A=, =@002S=, …) track entity lifecycle transitions. | 28 | *Stability* | Hash prefixes remain constant across state changes; only version and state suffixes evolve. | 29 | *Auditability* | Every entity can be serialized, verified, and reconstructed without hidden dependencies. | 30 | *Simplicity* | Pure-Python, zero external libraries, self-contained and easy to embed. | 31 |----------------|--------------------------------------------------------------------------------------------------------| 32 33 * Flex-O ID Structure 34 35 Each entity carries a unique *Flex-O ID*, generated by =FlexOID.generate()=. 36 37 #+BEGIN_EXAMPLE 38 AF-Q250101-9A4C2D@003S 39 #+END_EXAMPLE 40 41 |-----------|----------|---------------------------------------------| 42 | Segment | Example | Meaning | 43 |-----------|----------|---------------------------------------------| 44 | *Domain* | =AF= | Logical scope (e.g. "Air Force") | 45 | *Type* | =Q= | Entity type (e.g. Question) | 46 | *Date* | =250101= | UTC creation date (YYMMDD) | 47 | *Hash* | =9A4C2D= | 6-digit BLAKE2s digest of canonical content | 48 | *Version* | =003= | Sequential version counter | 49 | *State* | =S= | Lifecycle state (=D=, =A=, =S=, =P=, =O=) | 50 |-----------|----------|---------------------------------------------| 51 52 Hash collisions within a single session are automatically disambiguated (=-1=, =-2=, …). 53 54 * Lifecycle States 55 56 |-----------------------|---------|-----------------------------| 57 | State | Abbrev. | Description | 58 |-----------------------|---------|-----------------------------| 59 | *DRAFT* | =D= | Editable, not yet validated | 60 | *APPROVED* | =A= | Reviewed and accepted | 61 | *APPROVED_AND_SIGNED* | =S= | Cryptographically signed | 62 | *PUBLISHED* | =P= | Released to consumers | 63 | *OBSOLETE* | =O= | Archived or replaced | 64 |-----------------------|---------|-----------------------------| 65 66 Transitions follow a strict progression: 67 #+BEGIN_EXAMPLE 68 DRAFT → APPROVED → APPROVED_AND_SIGNED → PUBLISHED → OBSOLETE 69 #+END_EXAMPLE 70 71 Version increments occur automatically for all *stable* transitions (APPROVED, SIGNED, PUBLISHED). 72 73 * Core Classes 74 75 ** =FlexOID= 76 77 A lightweight immutable class representing the full identity of an entity. 78 79 *Highlights* 80 - =generate(domain, etype, estate, text, version=1)= → create a new ID 81 - =next_version(oid)= → increment version safely 82 - =clone_new_base(domain, etype, estate, text)= → start a new lineage 83 - Deterministic prefix, state-dependent signature 84 85 ** =FlexoEntity= 86 Abstract base class for all versioned entities (e.g., Question, Exam, Catalog). 87 88 Implements: 89 - ID lifecycle management (=approve()=, =sign()=, =publish()=, =obsolete()=) 90 - JSON serialization (=to_json()=, =from_json()=) 91 - Integrity verification (=verify_integrity(entity)=) 92 - Controlled state transitions with automatic timestamps 93 94 Subclasses define a single property: 95 96 #+BEGIN_SRC python 97 @property 98 def text_seed(self) -> str: 99 """Canonical text or core content for hashing.""" 100 #+END_SRC 101 102 * Integrity Verification 103 104 Each entity can self-verify its integrity: 105 106 #+BEGIN_SRC python 107 entity = Question("AF", EntityType.QUESTION, "What is Ohm’s law?") 108 json_str = entity.to_json() 109 reloaded = Question.from_json(json_str) 110 111 assert FlexoEntity.verify_integrity(reloaded) 112 #+END_SRC 113 114 If the file is tampered with (e.g. "Ohm’s" → "Omm’s"), verification fails: 115 116 #+BEGIN_SRC python 117 assert not FlexoEntity.verify_integrity(reloaded) 118 #+END_SRC 119 120 * Example 121 #+BEGIN_SRC python 122 from flexoentity.versioned_entity import FlexoEntity, EntityType, EntityState 123 124 class Question(FlexoEntity): 125 def __init__(self, domain, text): 126 self._text = text 127 super().__init__(domain, EntityType.QUESTION) 128 129 @property 130 def text_seed(self): 131 return self._text 132 133 * Usage 134 #+BEGIN_SRC python 135 q = Question("AF", "What is Ohm’s law?") 136 print(q.flexo_id) # AF-Q250101-9A4C2D@001D 137 q.approve() 138 print(q.flexo_id) # AF-Q250101-9A4C2D@002A 139 q.sign() 140 print(q.flexo_id) # AF-Q250101-9A4C2D@003S 141 #+END_SRC 142 143 * JSON Example 144 #+BEGIN_SRC json 145 { 146 "domain": "AF", 147 "etype": "QUESTION", 148 "text_seed": "What is Ohm’s law?", 149 "state": "APPROVED_AND_SIGNED", 150 "version": 3, 151 "flexo_id": "AF-Q250101-9A4C2D@003S", 152 "signature": "1E3A9F2A8B7C4D11", 153 "created_at": "2025-10-20T11:08:26Z", 154 "updated_at": "2025-10-20T11:12:44Z" 155 } 156 #+END_SRC 157 158 * Entity Type and State Codes 159 160 |-------------|------|------------------------------| 161 | EntityType | Code | Typical Use | 162 |-------------|------|------------------------------| 163 | QUESTION | Q | Exam question | 164 | CATALOG | CAT | Question or media collection | 165 | EXAM | EX | Composed test instance | 166 | DATABASE | DB | Persistent store | 167 | CERTIFICATE | CERT | Digital or approval document | 168 |-------------|------|------------------------------| 169 170 |---------------------|------|-------------------| 171 | EntityState | Code | Meaning | 172 |---------------------|------|-------------------| 173 | DRAFT | D | Work in progress | 174 | APPROVED | A | Reviewed | 175 | APPROVED_AND_SIGNED | S | Signed version | 176 | PUBLISHED | P | Publicly released | 177 | OBSOLETE | O | Deprecated | 178 |---------------------|------|-------------------| 179 180 * Design Notes 181 - *Hash Stability:* Only domain, entity type, and content text influence the hash. 182 This ensures consistent prefixes across state changes. 183 - *State-Dependent Signatures:* Each lifecycle stage has its own signature seed. 184 Modifying a file without re-signing invalidates integrity. 185 - *Obsolescence Threshold:* Version numbers above 900 trigger warnings; 186 beyond 999 are considered obsolete. 187 - *Clone Lineages:* Cloning an entity resets versioning but preserves metadata lineage. 188 189 * Dependencies 190 - Python 3.11+ 191 - Standard library only (=hashlib=, =json=, =datetime=, =enum=, =dataclasses=) 192 193 No external packages. Fully compatible with *Guix*, *air-gapped* deployments, and *reproducible builds*. 194 195 * Integration 196 `flexoentity` is imported by higher-level modules such as: 197 198 - *Flex-O-Grader* → manages question catalogs and exam bundles 199 - *Flex-O-Vault* → provides persistent media storage with metadata integrity 200 - *Flex-O-Drill* → uses versioned entities for training simulations 201 202 All share the same identity and versioning logic — ensuring that 203 *what was approved, signed, and published remains provably authentic.* 204 205 * License 206 MIT License 2025 207 Part of the *Flex-O family* by Flex-O-Dyne GmbH 208 Designed for reproducible, audit-ready, human-centered software.
Note:
See TracChangeset
for help on using the changeset viewer.
