368 lines
6.3 KiB
Markdown
368 lines
6.3 KiB
Markdown
# Ticket #022
|
|
|
|
## 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
|
|
|
|
- [ ] 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
|
|
|
|
```text
|
|
feat(database): initialize investigation database
|
|
```
|