Changes between Version 1 and Version 2 of WikiStart


Ignore:
Timestamp:
11/25/25 14:09:42 (5 days ago)
Author:
enno
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • WikiStart

    v1 v2  
    1 = Welcome to Trac
    2 
    3 Trac is a '''minimalistic''' approach to '''web-based''' management of
    4 '''software projects'''. Its goal is to simplify effective tracking and
    5 handling of software issues, enhancements and overall progress.
    6 
    7 All aspects of Trac have been designed with the single goal to
    8 '''help developers write great software''' while '''staying out of the way'''
    9 and imposing as little as possible on a team's established process and
    10 culture.
    11 
    12 As all Wiki pages, this page is editable, this means that you can
    13 modify the contents of this page simply by using your
    14 web-browser. Simply click on the "Edit this page" link at the bottom
    15 of the page. WikiFormatting will give you a detailed description of
    16 available Wiki formatting commands.
    17 
    18 "[wiki:TracAdmin trac-admin] ''yourenvdir'' initenv" created
    19 a new Trac environment, containing a default set of wiki pages and some sample
    20 data. This newly created environment also contains
    21 [wiki:TracGuide documentation] to help you get started with your project.
    22 
    23 You can use [wiki:TracAdmin trac-admin] to configure
    24 [http://trac.edgewall.org/ Trac] to better fit your project, especially in
    25 regard to ''components'', ''versions'' and ''milestones''.
    26 
    27 
    28 TracGuide is a good place to start.
    29 
    30 Enjoy! [[BR]]
    31 ''The Trac Team''
    32 
    33 == Starting Points
    34 
    35  * TracGuide --  Built-in Documentation
    36  * [http://trac.edgewall.org/ The Trac project] -- Trac Open Source Project
    37  * [http://trac.edgewall.org/wiki/TracFaq Trac FAQ] -- Frequently Asked Questions
    38  * TracSupport --  Trac Support
    39 
    40 For a complete list of local wiki pages, see TitleIndex.
     1* Overview
     2
     3`flexoentity` provides the *identity and lifecycle backbone* for all Flex-O components 
     4(Flex-O-Grader, Flex-O-Vault, Flex-O-Drill, …).
     5
     6It defines how entities such as questions, media, catalogs, and exams are *identified, versioned, signed, and verified* — all without any external database dependencies.
     7
     8At its heart lie two modules:
     9
     10- =id_factory.py= – robust, cryptographically-verifiable *Flex-O ID generator*
     11- =flexo_entity.py= – abstract *base class for all versioned entities*
     12
     13Together, they form a compact yet powerful foundation for audit-ready, reproducible data structures across offline and air-gapped deployments.
     14
     15- Design Goals
     16
     17|----------------|--------------------------------------------------------------------------------------------------------|
     18| Goal           | Description                                                                                            |
     19|----------------|--------------------------------------------------------------------------------------------------------|
     20| *Determinism*  | IDs are derived from canonicalized entity content — identical input always yields identical ID prefix. |
     21| *Integrity*    | BLAKE2s hashing and digital signatures protect against manual tampering.                               |
     22| *Traceability* | Version numbers (=@001A=, =@002S=, …) track entity lifecycle transitions.                              |
     23| *Stability*    | Hash prefixes remain constant across state changes; only version and state suffixes evolve.            |
     24| *Auditability* | Every entity can be serialized, verified, and reconstructed without hidden dependencies.               |
     25| *Simplicity*   | Pure-Python, zero external libraries, self-contained and easy to embed.                                |
     26|----------------|--------------------------------------------------------------------------------------------------------|
     27
     28* Flex-O ID Structure
     29
     30Each entity carries a unique *Flex-O ID*, generated by =FlexOID.generate()=.
     31
     32#+BEGIN_EXAMPLE
     33AF-I250101-9A4C2D@003S
     34#+END_EXAMPLE
     35
     36|-----------+-----------------+----------------------------------------------|
     37| Segment   | Example         | Meaning                                      |
     38|-----------+-----------------+----------------------------------------------|
     39| *Domain*  | =AF or PY_LANG= | Uppercase - Logical scope (e.g. "Air Force") |
     40| *Type*    | =I=             | Entity type (e.g. ITEM)                      |
     41| *Date*    | =250101=        | UTC creation date (YYMMDD)                   |
     42| *Hash*    | =9A4C2D4F6E53=  | 12-digit BLAKE2s digest of canonical content |
     43| *Version* | =003=           | Sequential version counter                   |
     44| *State*   | =S=             | Lifecycle state (D, A, S, P, O)              |
     45|-----------+-----------------+----------------------------------------------|
     46
     47
     48* Lifecycle States
     49
     50|-----------------------|---------|-----------------------------|
     51| State                 | Abbrev. | Description                 |
     52|-----------------------|---------|-----------------------------|
     53| *DRAFT*               | =D=     | Editable, not yet validated |
     54| *APPROVED*            | =A=     | Reviewed and accepted       |
     55| *APPROVED_AND_SIGNED* | =S=     | Cryptographically signed    |
     56| *PUBLISHED*           | =P=     | Released to consumers       |
     57| *OBSOLETE*            | =O=     | Archived or replaced        |
     58|-----------------------|---------|-----------------------------|
     59
     60Transitions follow a strict progression:
     61#+BEGIN_EXAMPLE
     62DRAFT -> APPROVED -> APPROVED_AND_SIGNED -> PUBLISHED -> OBSOLETE
     63#+END_EXAMPLE
     64
     65Only DRAFT entities can be deleted - all others got OBSOLETE mark instead
     66
     67* Core Classes
     68
     69** FlexOID
     70
     71A lightweight immutable class representing the full identity of an entity.
     72
     73*Highlights*
     74- safe_generate(domain, entity_type, estate, text, version=1, repo) -> create a new ID
     75- next_version(oid) -> increment version safely
     76- clone_new_base(domain, entity_type, estate, text) -> start a new lineage
     77- Deterministic prefix, state-dependent signature
     78
     79** =FlexoEntity=
     80Abstract base class for all versioned entities (e.g., Question, Exam, Catalog).
     81
     82Implements:
     83- ID lifecycle management (approve(), sign(), publish(), obsolete())
     84- Serialization (to_json(), from_json(), to_dict(), from_dict())
     85- Integrity verification (verify_integrity(entity))
     86- Controlled state transitions with automatic timestamps
     87
     88Subclasses define a single property:
     89
     90#+BEGIN_SRC python
     91@property
     92def text_seed(self) -> str:
     93    """Canonical text or core content for hashing."""
     94#+END_SRC
     95
     96* Integrity Verification
     97
     98Each entity can self-verify its integrity:
     99
     100#+BEGIN_SRC python
     101entity = Question.with_domain_id(domain_id="AF", text="What is Ohm’s law?", topic="Electronics")
     102json_str = entity.to_json()
     103reloaded = Question.from_json(json_str)
     104
     105assert FlexoEntity.verify_integrity(reloaded)
     106#+END_SRC
     107
     108If the file is tampered with (e.g. "Ohm’s" → "Omm’s"), verification fails:
     109
     110* Real World Example
     111
     112Below you can see the implementation of a dedicated FlexoEntity class, used for Domains.
     113We set an ENTITY_TYPE and define the needed fields in the data class. We define how to create
     114a default object, the text_seed (it is easy because the domain id is unique and therefore sufficient)
     115and the methods for serialization.
     116
     117#+BEGIN_SRC python
     118from uuid import UUID
     119from dataclasses import dataclass
     120from flexoentity import FlexOID, FlexoEntity, EntityType
     121
     122@dataclass
     123class Domain(FlexoEntity):
     124    """
     125    I am a helper class to provide more information than just a
     126    domain abbreviation in FlexOID, doing mapping and management
     127    """
     128
     129    ENTITY_TYPE = EntityType.DOMAIN
     130
     131    fullname: str = ""
     132    description: str = ""
     133    classification: str = "UNCLASSIFIED"
     134
     135    @classmethod
     136    def default(cls):
     137        """Return the default domain object."""
     138        return cls.with_domain_id(domain_id="GEN_GENERIC",
     139                                  fullname="Generic Domain", classification="UNCLASSIFIED")
     140
     141    @property
     142    def text_seed(self) -> str:
     143        return self.domain_id
     144
     145    def to_dict(self):
     146        base = super().to_dict()
     147        base.update({
     148            "flexo_id": self.flexo_id,
     149            "domain_id": self.domain_id,
     150            "fullname": self.fullname,
     151            "description": self.description,
     152            "classification": self.classification,
     153        })
     154        return base
     155
     156    @classmethod
     157    def from_dict(cls, data):
     158        # Must have flexo_id
     159        if "flexo_id" not in data:
     160            raise ValueError("Domain serialization missing 'flexo_id'.")
     161
     162        flexo_id = FlexOID(data["flexo_id"])
     163
     164        obj = cls(
     165            fullname=data.get("fullname", ""),
     166            description=data.get("description", ""),
     167            classification=data.get("classification", "UNCLASSIFIED"),
     168            flexo_id=flexo_id,
     169            _in_factory=True
     170        )
     171
     172        # Restore metadata
     173        obj.origin = data.get("origin")
     174        obj.fingerprint = data.get("fingerprint", "")
     175        obj.originator_id = (
     176            UUID(data["originator_id"]) if data.get("originator_id") else None
     177        )
     178        obj.owner_id = (
     179            UUID(data["owner_id"]) if data.get("owner_id") else None
     180        )
     181
     182        return obj
     183#+END_SRC
     184       
     185* Usage
     186#+BEGIN_SRC python
     187d = Domain.default()
     188print(d.flexo_id)             # GEN_GENERIC-D251124-67C2CAE292CE@001D
     189d.approve()
     190print(d.flexo_id)             # GEN_GENERIC-D251124-67C2CAE292CE@001A
     191d.sign()
     192print(d.flexo_id)             # GEN_GENERIC-D251124-67C2CAE292CE@001S
     193#+END_SRC
     194
     195* Serialization Example
     196
     197to_dict()
     198
     199#+BEGIN_SRC python
     200{
     201    'flexo_id': FlexOID(GEN_GENERIC-D251124-29CE0F4BE59D@001S),
     202    'fingerprint': '534BD2EC5C5511F1',
     203    'origin': FlexOID(GEN_GENERIC-D251124-67C2CAE292CE@001D),
     204    'originator_id': '00000000-0000-0000-0000-000000000000',
     205    'owner_id': '00000000-0000-0000-0000-000000000000',
     206    'domain_id': 'GEN_GENERIC',
     207    'fullname': 'Generic Domain',
     208    'description': '',
     209    'classification': 'UNCLASSIFIED'}
     210#+END_SRC
     211
     212to_json()
     213
     214#+BEGIN_SRC js
     215{
     216        "flexo_id": "GEN_GENERIC-D251124-29CE0F4BE59D@001S",
     217        "fingerprint": "534BD2EC5C5511F1",
     218        "origin": "GEN_GENERIC-D251124-67C2CAE292CE@001D",
     219        "originator_id": "00000000-0000-0000-0000-000000000000",
     220        "owner_id": "00000000-0000-0000-0000-000000000000",
     221        "domain_id": "GEN_GENERIC",
     222        "fullname": "Generic Domain",
     223        "description": "",
     224        "classification": "UNCLASSIFIED"
     225}
     226#+END_SRC
     227
     228
     229* Entity Type and State Codes
     230
     231|-------------+------+----------------------------------------------------------------------------|
     232| EntityType  | Code | Typical Use                                                                |
     233|-------------+------+----------------------------------------------------------------------------|
     234| GENERIC     | G    | Generic entities that does not fit other types yet or are temporarily only |
     235| DOMAIN      | D    | Every Domain is of this type                                               |
     236| MEDIA       | M    | Every media item belongs to this type, e.g. Pictures, Audio, Video         |
     237| ITEM        | I    | An Entity what is usually used in a collection, e.g. Questions in a test   |
     238| COLLECTION  | C    | A collection of items, as an Exam or a catalog                             |
     239| TEXT        | T    | A text document                                                            |
     240| HANDOUT     | H    | A published document                                                       |
     241| OUTPUT      | O    | The output of a computation                                                |
     242| RECORD      | R    | Record type data, as bibliography entries                                  |
     243| SESSION     | S    | A unique session, e.g. managed by a session manager
     244| USER        | U    | User objects                                                               |
     245| CONFIG      | F    | CONFIG files that need to be tracked over time and state                   |
     246| EVENT       | E    | Events that have to be tracked over time, as status messages or orders     |
     247| ATTESTATION | X    | Entities that attest a formal technical (not human) check e.g. Signatures  |
     248|-------------+------+----------------------------------------------------------------------------|
     249
     250|---------------------|------|-------------------|
     251| EntityState         | Code | Meaning           |
     252|---------------------|------|-------------------|
     253| DRAFT               | D    | Work in progress  |
     254| APPROVED            | A    | Reviewed          |
     255| APPROVED_AND_SIGNED | S    | Signed version    |
     256| PUBLISHED           | P    | Publicly released |
     257| OBSOLETE            | O    | Deprecated        |
     258|---------------------|------|-------------------|
     259
     260* Design Notes
     261- *Hash Stability:* Only domain, entity type, and content text influence the hash.
     262  This ensures consistent prefixes across state changes.
     263- *State-Dependent Signatures:* Each lifecycle stage has its own signature seed.
     264  Modifying a file without re-signing invalidates integrity.
     265- *Obsolescence Threshold:* Version numbers above 900 trigger warnings;
     266  beyond 999 are considered obsolete.
     267- *Clone Lineages:* Cloning an entity resets versioning but preserves metadata lineage.
     268
     269* Dependencies
     270- Python 3.11+
     271- Standard library only (=hashlib=, =json=, =datetime=, =enum=, =dataclasses=)
     272
     273No external packages. Fully compatible with *Guix*, *air-gapped* deployments, and *reproducible builds*.
     274
     275* Integration
     276`flexoentity` is imported by higher-level modules such as:
     277
     278- *Flex-O-Grader* → manages question catalogs and exam bundles
     279- *Flex-O-Vault* → provides persistent media storage with metadata integrity
     280- *Flex-O-Drill* → uses versioned entities for training simulations
     281
     282All share the same identity and versioning logic — ensuring that
     283*what was approved, signed, and published remains provably authentic.*
     284
     285* License
     286MIT License 2025
     287Part of the *Flex-O family* by Flex-O-Dyne GmbH
     288Designed for reproducible, audit-ready, human-centered software.