Initialiser la base SQLite d'une enquête. #23

Closed
opened 2026-07-18 08:41:59 +02:00 by fy59 · 0 comments
Owner

Titre

Initialiser la base SQLite d'une enquête.


Objectif

Créer et initialiser correctement le fichier :

00_BaseDeDonnees/Enquete.sqlite

avec un premier schéma SQLite versionné.

La base doit contenir les métadonnées minimales permettant d'identifier
l'enquête et la version du schéma.


Architecture

InvestigationProject
        │
        ▼
Database
        │
        ▼
SQLite

InvestigationProject orchestre la création de l'enquête.

Le module Database est seul responsable de l'ouverture de SQLite,
de l'exécution du schéma et de la fermeture de la base.


Responsabilités

InvestigationProject

Le module doit :

  • créer l'arborescence ;
  • demander au module Database d'initialiser Enquete.sqlite ;
  • considérer la création comme échouée si l'initialisation SQLite échoue ;
  • nettoyer toute l'enquête créée en cas d'échec.

Database

Le module doit :

  • ouvrir ou créer le fichier SQLite ;
  • démarrer une transaction ;
  • créer le schéma initial ;
  • insérer les métadonnées ;
  • valider la transaction ;
  • annuler la transaction en cas d'erreur ;
  • fermer proprement la connexion.

Nouveaux fichiers

include/database/database.h
src/database/database.c

Éventuellement :

include/database/schema.h
src/database/schema.c

si le schéma devient trop volumineux pour rester dans database.c.

Pour ce ticket, un seul module database.c est acceptable.


Interface publique attendue

bool database_initialize(
    const char *database_path
);

La fonction retourne :

true

si la base a été correctement initialisée.

Elle retourne :

false

en cas d'erreur.


Schéma initial

Table metadata

CREATE TABLE metadata
(
    key   TEXT PRIMARY KEY,
    value TEXT NOT NULL
);

Métadonnées obligatoires

schema_version
application
created_at
investigation_uuid

Valeurs attendues :

schema_version     = 1
application        = Labfy Investigation
created_at         = date UTC ISO 8601
investigation_uuid = UUID unique

Exemple :

2026-07-14T18:42:15Z

Table investigation

Créer également une table minimale représentant l'enquête :

CREATE TABLE investigation
(
    id          INTEGER PRIMARY KEY CHECK (id = 1),
    name        TEXT NOT NULL,
    root_path   TEXT NOT NULL,
    created_at  TEXT NOT NULL
);

La table contient une seule ligne correspondant à l'enquête courante.


Données nécessaires

database_initialize() doit recevoir suffisamment d'informations pour
initialiser correctement la base.

L'interface pourra donc évoluer vers :

bool database_initialize(
    const char *database_path,
    const char *investigation_name,
    const char *investigation_root_path
);

Cette signature est préférée pour éviter que le module Database
reconstruise ou devine des informations métier.


UUID

L'UUID doit être généré avec GLib :

g_uuid_string_random()

La chaîne retournée doit être libérée avec :

g_free(uuid);

Date de création

La date doit être produite en UTC avec GLib.

Format attendu :

YYYY-MM-DDTHH:MM:SSZ

La date doit être enregistrée à la fois :

  • dans metadata.created_at ;
  • dans investigation.created_at.

Transaction

Toute l'initialisation doit se dérouler dans une transaction :

BEGIN IMMEDIATE;

Puis :

COMMIT;

En cas d'erreur :

ROLLBACK;

Une base partiellement initialisée ne doit jamais être considérée comme valide.


Intégration avec InvestigationProject

investigation_project_create() ne doit plus créer un fichier vide avec :

g_file_set_contents(...)

Il doit construire le chemin de la base puis appeler :

database_initialize(
    database_path,
    investigation_name,
    investigation_path
);

Si l'appel échoue :

  • le fichier SQLite éventuel est supprimé ;
  • tous les dossiers créés sont supprimés ;
  • investigation_project_create() retourne NULL.

Validation

À partir de ce ticket, investigation_project_validate() doit toujours
vérifier la présence du fichier SQLite, mais pas encore son contenu SQL.

La validation du schéma sera ajoutée dans un prochain ticket dédié.


Hors périmètre

Ce ticket ne doit pas :

  • créer les tables Preuves ;
  • créer les tables Entites ;
  • créer les relations ;
  • gérer les migrations ;
  • ouvrir une enquête existante ;
  • modifier GTK ;
  • exposer directement sqlite3 * hors du module Database.

Contraintes techniques

  • C17 ;
  • SQLite3 ;
  • GLib ;
  • aucune dépendance GTK ;
  • aucun état global ;
  • requêtes SQL centralisées dans database.c ;
  • fermeture garantie de la connexion ;
  • transaction obligatoire ;
  • documentation Doxygen ;
  • compilation sans warning.

Tests

Créer :

tests/test_database.c

Le test doit :

  • créer un dossier temporaire ;
  • initialiser une base SQLite ;
  • vérifier que le fichier existe ;
  • ouvrir la base en lecture ;
  • vérifier la présence de la table metadata ;
  • vérifier la présence de la table investigation ;
  • vérifier schema_version = 1 ;
  • vérifier application = Labfy Investigation ;
  • vérifier que created_at n'est pas vide ;
  • vérifier que l'UUID n'est pas vide ;
  • vérifier la ligne unique de la table investigation ;
  • vérifier le nom et le chemin racine ;
  • vérifier qu'une initialisation sur un chemin invalide échoue ;
  • nettoyer complètement les fichiers temporaires.

Faire également évoluer :

tests/test_investigation_project.c

pour vérifier que la base créée n'est plus vide.


Critères d'acceptation

  • Le projet compile sans warning.
  • make test reste entièrement valide.
  • Enquete.sqlite est une vraie base SQLite.
  • La table metadata existe.
  • La table investigation existe.
  • schema_version vaut 1.
  • Une date UTC est enregistrée.
  • Un UUID est généré.
  • L'enquête est enregistrée dans la base.
  • L'initialisation est transactionnelle.
  • Toute erreur provoque un nettoyage complet.
  • Aucun type sqlite3 * n'est exposé publiquement.
  • Aucune dépendance GTK.

Commit attendu

feat(database): initialize investigation database
## Titre Initialiser la base SQLite d'une enquête. --- ## Objectif Créer et initialiser correctement le fichier : ```text 00_BaseDeDonnees/Enquete.sqlite ``` avec un premier schéma SQLite versionné. La base doit contenir les métadonnées minimales permettant d'identifier l'enquête et la version du schéma. --- ## Architecture ```text InvestigationProject │ ▼ Database │ ▼ SQLite ``` `InvestigationProject` orchestre la création de l'enquête. Le module `Database` est seul responsable de l'ouverture de SQLite, de l'exécution du schéma et de la fermeture de la base. --- ## Responsabilités ### InvestigationProject Le module doit : - créer l'arborescence ; - demander au module `Database` d'initialiser `Enquete.sqlite` ; - considérer la création comme échouée si l'initialisation SQLite échoue ; - nettoyer toute l'enquête créée en cas d'échec. ### Database Le module doit : - ouvrir ou créer le fichier SQLite ; - démarrer une transaction ; - créer le schéma initial ; - insérer les métadonnées ; - valider la transaction ; - annuler la transaction en cas d'erreur ; - fermer proprement la connexion. --- ## Nouveaux fichiers ```text include/database/database.h src/database/database.c ``` Éventuellement : ```text include/database/schema.h src/database/schema.c ``` si le schéma devient trop volumineux pour rester dans `database.c`. Pour ce ticket, un seul module `database.c` est acceptable. --- ## Interface publique attendue ```c bool database_initialize( const char *database_path ); ``` La fonction retourne : ```c true ``` si la base a été correctement initialisée. Elle retourne : ```c false ``` en cas d'erreur. --- ## Schéma initial ### Table `metadata` ```sql CREATE TABLE metadata ( key TEXT PRIMARY KEY, value TEXT NOT NULL ); ``` ### Métadonnées obligatoires ```text schema_version application created_at investigation_uuid ``` Valeurs attendues : ```text schema_version = 1 application = Labfy Investigation created_at = date UTC ISO 8601 investigation_uuid = UUID unique ``` Exemple : ```text 2026-07-14T18:42:15Z ``` --- ## Table `investigation` Créer également une table minimale représentant l'enquête : ```sql CREATE TABLE investigation ( id INTEGER PRIMARY KEY CHECK (id = 1), name TEXT NOT NULL, root_path TEXT NOT NULL, created_at TEXT NOT NULL ); ``` La table contient une seule ligne correspondant à l'enquête courante. --- ## Données nécessaires `database_initialize()` doit recevoir suffisamment d'informations pour initialiser correctement la base. L'interface pourra donc évoluer vers : ```c bool database_initialize( const char *database_path, const char *investigation_name, const char *investigation_root_path ); ``` Cette signature est préférée pour éviter que le module `Database` reconstruise ou devine des informations métier. --- ## UUID L'UUID doit être généré avec GLib : ```c g_uuid_string_random() ``` La chaîne retournée doit être libérée avec : ```c g_free(uuid); ``` --- ## Date de création La date doit être produite en UTC avec GLib. Format attendu : ```text YYYY-MM-DDTHH:MM:SSZ ``` La date doit être enregistrée à la fois : - dans `metadata.created_at` ; - dans `investigation.created_at`. --- ## Transaction Toute l'initialisation doit se dérouler dans une transaction : ```sql BEGIN IMMEDIATE; ``` Puis : ```sql COMMIT; ``` En cas d'erreur : ```sql ROLLBACK; ``` Une base partiellement initialisée ne doit jamais être considérée comme valide. --- ## Intégration avec InvestigationProject `investigation_project_create()` ne doit plus créer un fichier vide avec : ```c g_file_set_contents(...) ``` Il doit construire le chemin de la base puis appeler : ```c database_initialize( database_path, investigation_name, investigation_path ); ``` Si l'appel échoue : - le fichier SQLite éventuel est supprimé ; - tous les dossiers créés sont supprimés ; - `investigation_project_create()` retourne `NULL`. --- ## Validation À partir de ce ticket, `investigation_project_validate()` doit toujours vérifier la présence du fichier SQLite, mais pas encore son contenu SQL. La validation du schéma sera ajoutée dans un prochain ticket dédié. --- ## Hors périmètre Ce ticket ne doit pas : - créer les tables Preuves ; - créer les tables Entites ; - créer les relations ; - gérer les migrations ; - ouvrir une enquête existante ; - modifier GTK ; - exposer directement `sqlite3 *` hors du module Database. --- ## Contraintes techniques - C17 ; - SQLite3 ; - GLib ; - aucune dépendance GTK ; - aucun état global ; - requêtes SQL centralisées dans `database.c` ; - fermeture garantie de la connexion ; - transaction obligatoire ; - documentation Doxygen ; - compilation sans warning. --- ## Tests Créer : ```text tests/test_database.c ``` Le test doit : - créer un dossier temporaire ; - initialiser une base SQLite ; - vérifier que le fichier existe ; - ouvrir la base en lecture ; - vérifier la présence de la table `metadata` ; - vérifier la présence de la table `investigation` ; - vérifier `schema_version = 1` ; - vérifier `application = Labfy Investigation` ; - vérifier que `created_at` n'est pas vide ; - vérifier que l'UUID n'est pas vide ; - vérifier la ligne unique de la table `investigation` ; - vérifier le nom et le chemin racine ; - vérifier qu'une initialisation sur un chemin invalide échoue ; - nettoyer complètement les fichiers temporaires. Faire également évoluer : ```text tests/test_investigation_project.c ``` pour vérifier que la base créée n'est plus vide. --- ## Critères d'acceptation - [x] Le projet compile sans warning. - [x] `make test` reste entièrement valide. - [x] `Enquete.sqlite` est une vraie base SQLite. - [x] La table `metadata` existe. - [x] La table `investigation` existe. - [x] `schema_version` vaut `1`. - [x] Une date UTC est enregistrée. - [x] Un UUID est généré. - [x] L'enquête est enregistrée dans la base. - [x] L'initialisation est transactionnelle. - [x] Toute erreur provoque un nettoyage complet. - [x] Aucun type `sqlite3 *` n'est exposé publiquement. - [x] Aucune dépendance GTK. --- ## Commit attendu ```text feat(database): initialize investigation database ```
fy59 closed this issue 2026-07-18 08:42:23 +02:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: fy59/labfy-investigation#23
No description provided.