Backend: 7 nouveaux endpoints (advance, assign, revoke, create-vote-session), services enrichis avec creation de sessions de vote, assignation de mandataire et revocation. 35 nouveaux tests (104 total). Frontend: store mandates, page cadrage decisions, detail mandats, composants DecisionWorkflow, DecisionCadrage, DecisionCard, MandateTimeline, MandateCard. Documentation mise a jour. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
329 lines
21 KiB
Markdown
329 lines
21 KiB
Markdown
---
|
|
title: Schema de base de donnees
|
|
description: Tables et relations de la base de donnees PostgreSQL
|
|
---
|
|
|
|
# Schema de base de donnees
|
|
|
|
Glibredecision utilise PostgreSQL 16 avec SQLAlchemy 2.0 en mode asynchrone (asyncpg). Toutes les cles primaires sont des UUID v4.
|
|
|
|
## Tables
|
|
|
|
### `duniter_identities`
|
|
|
|
Identites Duniter V2 connues de la plateforme.
|
|
|
|
| Colonne | Type | Description |
|
|
| -------------- | ------------ | ---------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| address | VARCHAR(64) | Adresse SS58 Duniter (unique, indexee) |
|
|
| display_name | VARCHAR(128) | Nom d'affichage |
|
|
| wot_status | VARCHAR(32) | Statut WoT : member, pending, revoked, unknown |
|
|
| is_smith | BOOLEAN | Membre Smith (forgeron) |
|
|
| is_techcomm | BOOLEAN | Membre du Comite Technique |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
| updated_at | TIMESTAMPTZ | Date de derniere mise a jour |
|
|
|
|
### `sessions`
|
|
|
|
Sessions d'authentification (tokens).
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------ | ------------ | ---------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| token_hash | VARCHAR(128) | Hash du token (unique, indexe) |
|
|
| identity_id | UUID (FK) | -> duniter_identities.id |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
| expires_at | TIMESTAMPTZ | Date d'expiration |
|
|
|
|
### `documents`
|
|
|
|
Documents de reference modulaires. Le cycle de vie d'un document suit les statuts `draft` -> `active` -> `archived`. Lors de l'archivage (Sprint 2), les champs `ipfs_cid` et `chain_anchor` sont renseignes automatiquement par le service sanctuaire.
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------ | ------------ | ----------------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| slug | VARCHAR(128) | Identifiant lisible (unique, indexe) |
|
|
| title | VARCHAR(256) | Titre du document |
|
|
| doc_type | VARCHAR(64) | Type : licence, engagement, reglement, constitution |
|
|
| version | VARCHAR(32) | Version semantique (defaut "0.1.0") |
|
|
| status | VARCHAR(32) | Statut : draft, active, archived |
|
|
| description | TEXT | Description du document |
|
|
| ipfs_cid | VARCHAR(128) | CID IPFS de la derniere version archivee (renseigne lors de l'archivage) |
|
|
| chain_anchor | VARCHAR(128) | Hash de transaction on-chain (renseigne lors de l'archivage) |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
| updated_at | TIMESTAMPTZ | Date de derniere mise a jour |
|
|
|
|
### `document_items`
|
|
|
|
Items individuels composant un document (clauses, regles, verifications, etc.). Chaque item peut etre modifie, supprime ou reordonne individuellement (Sprint 2). Le champ `current_text` est mis a jour automatiquement lorsqu'une version est acceptee.
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------------- | ------------ | ------------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| document_id | UUID (FK) | -> documents.id (cascade delete) |
|
|
| position | VARCHAR(16) | Numero de position ("1", "1.1", "3.2") |
|
|
| item_type | VARCHAR(32) | Type : clause, rule, verification, preamble, section |
|
|
| title | VARCHAR(256) | Titre de l'item |
|
|
| current_text | TEXT | Texte courant de l'item (mis a jour lors de l'acceptation d'une version) |
|
|
| voting_protocol_id | UUID (FK) | -> voting_protocols.id (protocole specifique) |
|
|
| sort_order | INTEGER | Ordre de tri (modifiable via endpoint reorder) |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
| updated_at | TIMESTAMPTZ | Date de derniere mise a jour |
|
|
|
|
### `item_versions`
|
|
|
|
Historique des versions proposees pour chaque item. Lors de l'acceptation d'une version (Sprint 2), le `current_text` de l'item parent est remplace par le `proposed_text` de la version, et toutes les autres versions en attente (`proposed`, `voting`) sont automatiquement rejetees.
|
|
|
|
| Colonne | Type | Description |
|
|
| -------------- | ------------ | ------------------------------------------------------ |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| item_id | UUID (FK) | -> document_items.id (cascade delete) |
|
|
| proposed_text | TEXT | Texte propose |
|
|
| diff_text | TEXT | Diff unifie entre texte courant et propose (genere automatiquement) |
|
|
| rationale | TEXT | Justification de la modification |
|
|
| status | VARCHAR(32) | Statut : proposed, voting, accepted, rejected |
|
|
| decision_id | UUID (FK) | -> decisions.id (decision associee) |
|
|
| proposed_by_id | UUID (FK) | -> duniter_identities.id (auteur de la proposition) |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
|
|
### `decisions`
|
|
|
|
Processus decisionnels multi-etapes. Le cycle de vie suit un ordre strict de statuts gere par le service `decision_service.advance_decision()`.
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------------- | ------------ | -------------------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| title | VARCHAR(256) | Titre de la decision |
|
|
| description | TEXT | Description |
|
|
| context | TEXT | Contexte additionnel (cadrage) |
|
|
| decision_type | VARCHAR(64) | Type : runtime_upgrade, document_change, mandate_vote, parameter_change, custom |
|
|
| status | VARCHAR(32) | Statut : draft, qualification, review, voting, executed, closed |
|
|
| voting_protocol_id | UUID (FK) | -> voting_protocols.id |
|
|
| created_by_id | UUID (FK) | -> duniter_identities.id |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
| updated_at | TIMESTAMPTZ | Date de derniere mise a jour |
|
|
|
|
**Workflow des statuts** : `draft` -> `qualification` -> `review` -> `voting` -> `executed` -> `closed`. La transition est geree par le service `advance_decision` qui complete l'etape active, active la suivante, et avance le statut global quand toutes les etapes sont terminees. La suppression n'est autorisee qu'en statut `draft`.
|
|
|
|
### `decision_steps`
|
|
|
|
Etapes d'un processus decisionnel. Chaque etape est traitee sequentiellement selon `step_order`. Le service `advance_decision` complete l'etape `active` et active la prochaine `pending`.
|
|
|
|
| Colonne | Type | Description |
|
|
| ---------------- | ------------ | -------------------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| decision_id | UUID (FK) | -> decisions.id (cascade delete) |
|
|
| step_order | INTEGER | Ordre de l'etape (0-indexed, determine la sequence) |
|
|
| step_type | VARCHAR(32) | Type : qualification, review, vote, execution, reporting |
|
|
| title | VARCHAR(256) | Titre de l'etape |
|
|
| description | TEXT | Description |
|
|
| status | VARCHAR(32) | Statut : pending, active, completed, skipped |
|
|
| vote_session_id | UUID (FK) | -> vote_sessions.id (renseigne via create-vote-session pour les etapes de type `vote`) |
|
|
| outcome | TEXT | Resultat de l'etape |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
|
|
**Types d'etapes** : `qualification` (verification recevabilite), `review` (examen communautaire), `vote` (session de vote formelle), `execution` (mise en oeuvre), `reporting` (compte-rendu). Les etapes de type `vote` sont les seules a pouvoir avoir un `vote_session_id` renseigne.
|
|
|
|
### `vote_sessions`
|
|
|
|
Sessions de vote avec snapshot des tailles WoT et decompte en temps reel.
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------------- | ------------ | ---------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| decision_id | UUID (FK) | -> decisions.id |
|
|
| item_version_id | UUID (FK) | -> item_versions.id |
|
|
| voting_protocol_id | UUID (FK) | -> voting_protocols.id |
|
|
| wot_size | INTEGER | Taille WoT au debut de la session |
|
|
| smith_size | INTEGER | Taille Smith au debut de la session |
|
|
| techcomm_size | INTEGER | Taille TechComm au debut de la session |
|
|
| starts_at | TIMESTAMPTZ | Date de debut |
|
|
| ends_at | TIMESTAMPTZ | Date de fin |
|
|
| status | VARCHAR(32) | Statut : open, closed, tallied |
|
|
| votes_for | INTEGER | Nombre de votes pour |
|
|
| votes_against | INTEGER | Nombre de votes contre |
|
|
| votes_total | INTEGER | Nombre total de votes |
|
|
| smith_votes_for | INTEGER | Votes pour des membres Smith |
|
|
| techcomm_votes_for | INTEGER | Votes pour des membres TechComm |
|
|
| threshold_required | FLOAT | Seuil calcule requis |
|
|
| result | VARCHAR(32) | Resultat : adopted, rejected, null |
|
|
| chain_recorded | BOOLEAN | Enregistre sur la blockchain |
|
|
| chain_tx_hash | VARCHAR(128) | Hash de la transaction on-chain |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
|
|
### `votes`
|
|
|
|
Votes individuels avec preuve cryptographique.
|
|
|
|
| Colonne | Type | Description |
|
|
| ---------------- | ------------ | -------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| session_id | UUID (FK) | -> vote_sessions.id |
|
|
| voter_id | UUID (FK) | -> duniter_identities.id |
|
|
| vote_value | VARCHAR(32) | Valeur : for, against, ou niveau nuance |
|
|
| nuanced_level | INTEGER | Niveau nuance (0-5) pour les votes nuances |
|
|
| comment | TEXT | Commentaire optionnel |
|
|
| signature | TEXT | Signature Ed25519 du payload |
|
|
| signed_payload | TEXT | Payload signe (pour verification) |
|
|
| voter_wot_status | VARCHAR(32) | Statut WoT du votant au moment du vote |
|
|
| voter_is_smith | BOOLEAN | Le votant est-il forgeron |
|
|
| voter_is_techcomm| BOOLEAN | Le votant est-il membre TechComm |
|
|
| is_active | BOOLEAN | Vote actif (false si remplace) |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
|
|
### `mandates`
|
|
|
|
Mandats assignes a des membres. Le cycle de vie suit un ordre strict de statuts gere par le service `mandate_service.advance_mandate()`. La revocation (`POST /mandates/{id}/revoke`) permet de passer directement au statut terminal `revoked`.
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------- | ------------ | ------------------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| title | VARCHAR(256) | Titre du mandat |
|
|
| description | TEXT | Description |
|
|
| mandate_type | VARCHAR(64) | Type : techcomm, smith, custom |
|
|
| status | VARCHAR(32) | Statut : draft, candidacy, voting, active, reporting, completed, revoked |
|
|
| mandatee_id | UUID (FK) | -> duniter_identities.id (titulaire du mandat, renseigne via `POST /mandates/{id}/assign`) |
|
|
| decision_id | UUID (FK) | -> decisions.id (decision associee, optionnel) |
|
|
| starts_at | TIMESTAMPTZ | Date de debut (renseignee lors de l'assignation) |
|
|
| ends_at | TIMESTAMPTZ | Date de fin (renseignee lors de l'assignation) |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
| updated_at | TIMESTAMPTZ | Date de derniere mise a jour |
|
|
|
|
**Workflow des statuts** : `draft` -> `candidacy` -> `voting` -> `active` -> `reporting` -> `completed`. Les statuts terminaux sont `completed` et `revoked`. La suppression n'est autorisee qu'en statut `draft`. La revocation est possible depuis les statuts `active` ou `reporting`.
|
|
|
|
### `mandate_steps`
|
|
|
|
Etapes du cycle de vie d'un mandat. Chaque etape est traitee sequentiellement selon `step_order`. Le service `advance_mandate` complete l'etape `active` et active la prochaine `pending`.
|
|
|
|
| Colonne | Type | Description |
|
|
| ---------------- | ------------ | ------------------------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| mandate_id | UUID (FK) | -> mandates.id (cascade delete) |
|
|
| step_order | INTEGER | Ordre de l'etape (0-indexed, determine la sequence) |
|
|
| step_type | VARCHAR(32) | Type : formulation, candidacy, vote, assignment, reporting, completion, revocation |
|
|
| title | VARCHAR(256) | Titre de l'etape |
|
|
| description | TEXT | Description |
|
|
| status | VARCHAR(32) | Statut : pending, active, completed, skipped |
|
|
| vote_session_id | UUID (FK) | -> vote_sessions.id (renseigne via create-vote-session pour les etapes de type `vote`) |
|
|
| outcome | TEXT | Resultat de l'etape |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
|
|
**Types d'etapes** : `formulation` (definition du mandat), `candidacy` (depot des candidatures), `vote` (election par vote WoT), `assignment` (attribution au candidat elu), `reporting` (compte-rendu), `completion` (fin normale), `revocation` (fin anticipee). Les etapes de type `vote` sont les seules a pouvoir avoir un `vote_session_id` renseigne.
|
|
|
|
### `voting_protocols`
|
|
|
|
Protocoles de vote reutilisables.
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------------ | ------------ | ----------------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| name | VARCHAR(128) | Nom du protocole |
|
|
| description | TEXT | Description |
|
|
| vote_type | VARCHAR(32) | Type de vote : binary, nuanced |
|
|
| formula_config_id | UUID (FK) | -> formula_configs.id |
|
|
| mode_params | VARCHAR(64) | Parametres compacts ("D30M50B.1G.2T.1") |
|
|
| is_meta_governed | BOOLEAN | Le protocole est-il sous meta-gouvernance |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
|
|
### `formula_configs`
|
|
|
|
Configurations de formules de seuil WoT.
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------------------- | ------------ | ----------------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| name | VARCHAR(128) | Nom de la configuration |
|
|
| description | TEXT | Description |
|
|
| duration_days | INTEGER | Duree du vote en jours |
|
|
| majority_pct | INTEGER | Pourcentage de majorite (0-100) |
|
|
| base_exponent | FLOAT | Exposant de base B |
|
|
| gradient_exponent | FLOAT | Exposant de gradient G |
|
|
| constant_base | FLOAT | Base constante C |
|
|
| smith_exponent | FLOAT | Exposant Smith S (null si non requis) |
|
|
| techcomm_exponent | FLOAT | Exposant TechComm T (null si non requis) |
|
|
| nuanced_min_participants | INTEGER | Participants minimum (vote nuance) |
|
|
| nuanced_threshold_pct | INTEGER | Seuil positif % (vote nuance) |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
|
|
### `sanctuary_entries`
|
|
|
|
Entrees du sanctuaire (archivage immuable). Le champ `reference_id` permet de retrouver toutes les entrees liees a un document, une decision ou une session de vote via l'endpoint `/by-reference/{reference_id}` (Sprint 2). L'endpoint `/verify` recalcule le hash et verifie la coherence IPFS/on-chain.
|
|
|
|
| Colonne | Type | Description |
|
|
| -------------- | ------------ | ------------------------------------------ |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| entry_type | VARCHAR(64) | Type : document, decision, vote_result |
|
|
| reference_id | UUID | UUID de l'entite source (indexe pour recherche par reference) |
|
|
| title | VARCHAR(256) | Titre |
|
|
| content_hash | VARCHAR(128) | Hash SHA-256 du contenu |
|
|
| ipfs_cid | VARCHAR(128) | CID IPFS (renseigne lors de l'upload) |
|
|
| chain_tx_hash | VARCHAR(128) | Hash de la transaction on-chain |
|
|
| chain_block | INTEGER | Numero de bloc de la transaction |
|
|
| metadata_json | TEXT | Metadonnees JSON supplementaires |
|
|
| created_at | TIMESTAMPTZ | Date de creation |
|
|
|
|
### `blockchain_cache`
|
|
|
|
Cache des donnees blockchain pour eviter les appels RPC repetes.
|
|
|
|
| Colonne | Type | Description |
|
|
| ------------ | ------------ | -------------------------------- |
|
|
| id | UUID (PK) | Identifiant unique |
|
|
| cache_key | VARCHAR(256) | Cle de cache (unique, indexee) |
|
|
| cache_value | JSONB | Valeur en cache |
|
|
| fetched_at | TIMESTAMPTZ | Date de recuperation |
|
|
| expires_at | TIMESTAMPTZ | Date d'expiration du cache |
|
|
|
|
## Diagramme des relations
|
|
|
|
```
|
|
duniter_identities
|
|
|-- 1:N --> sessions
|
|
|-- 1:N --> votes (voter_id)
|
|
|-- 1:N --> item_versions (proposed_by_id)
|
|
|-- 1:N --> decisions (created_by_id)
|
|
|-- 1:N --> mandates (mandatee_id)
|
|
|
|
documents
|
|
|-- 1:N --> document_items
|
|
|-- 1:N ..> sanctuary_entries (via reference_id, non FK)
|
|
|
|
document_items
|
|
|-- 1:N --> item_versions (cascade delete)
|
|
|-- N:1 --> voting_protocols
|
|
|
|
item_versions
|
|
|-- N:1 --> decisions
|
|
|
|
decisions
|
|
|-- 1:N --> decision_steps
|
|
|-- 1:N ..> sanctuary_entries (via reference_id, non FK)
|
|
|
|
decision_steps
|
|
|-- N:1 --> vote_sessions
|
|
|
|
vote_sessions
|
|
|-- 1:N --> votes
|
|
|-- N:1 --> voting_protocols
|
|
|-- 1:N ..> sanctuary_entries (via reference_id, non FK)
|
|
|
|
mandates
|
|
|-- 1:N --> mandate_steps
|
|
|-- N:1 --> decisions
|
|
|
|
mandate_steps
|
|
|-- N:1 --> vote_sessions
|
|
|
|
voting_protocols
|
|
|-- N:1 --> formula_configs
|
|
|
|
formula_configs
|
|
|-- 1:N --> voting_protocols
|
|
|
|
sanctuary_entries
|
|
|-- reference_id ..> documents | decisions | vote_sessions (lien logique)
|
|
```
|
|
|
|
> **Note Sprint 2** : Les liens `..>` (pointilles) representent des references logiques via le champ `reference_id` de `sanctuary_entries`. Ce ne sont pas des cles etrangeres PostgreSQL car `reference_id` peut pointer vers differentes tables selon le `entry_type`.
|