diff --git a/documentation/content/docs/_meta.json b/documentation/content/docs/_meta.json new file mode 100644 index 0000000..77e099f --- /dev/null +++ b/documentation/content/docs/_meta.json @@ -0,0 +1,9 @@ +{ + "index": "Introduction", + "stack": "Stack Technologique", + "database": "Modèle de Données", + "api": "API & Intégrations", + "security": "Sécurité", + "compliance": "Conformité (RGPD)", + "deployment": "Déploiement & Tests" +} diff --git a/documentation/content/docs/api.mdx b/documentation/content/docs/api.mdx new file mode 100644 index 0000000..4429ca6 --- /dev/null +++ b/documentation/content/docs/api.mdx @@ -0,0 +1,21 @@ +--- +title: API & Intégrations +description: Documentation des API et services tiers +--- + +## 🔌 API & Intégrations + +### Documentation API + +Documentation MDX. + +### Authentification + +Le système utilise plusieurs méthodes d'authentification sécurisées : +- **Sessions (JWT)** : Utilisation de JSON Web Tokens signés pour les sessions utilisateurs via le web. Les sessions sont persistées en base de données (`sessions`) pour permettre la révocation (Logout) et le suivi des appareils connectés. +- **API Keys** : Pour les intégrations programmatiques. Les clés sont hachées en base de données (`key_hash`) et associées à un utilisateur. Elles peuvent être nommées et révoquées individuellement. +- **Double Authentification (2FA)** : Support natif (TOTP) avec secret chiffré en base de données. + +### Webhooks / Services Externes + +Liste des intégrations tierces. diff --git a/documentation/content/docs/compliance.mdx b/documentation/content/docs/compliance.mdx new file mode 100644 index 0000000..e50df44 --- /dev/null +++ b/documentation/content/docs/compliance.mdx @@ -0,0 +1,44 @@ +--- +title: Conformité (RGPD & France) +description: Mesures prises pour la conformité au RGPD et aux réglementations françaises. +--- + +## ⚖️ Conformité Réglementaire + +Le projet Memegoat s'inscrit dans une démarche de respect de la vie privée et de protection des données à caractère personnel, conformément au **Règlement Général sur la Protection des Données (RGPD)** de l'Union Européenne et aux recommandations de la **CNIL**. + +### 🛡️ Principes Fondamentaux + +- **Minimisation des données** : Seules les données strictement nécessaires au fonctionnement du service sont collectées. +- **Transparence** : Les utilisateurs sont informés de la finalité des traitements de leurs données. +- **Sécurité** : Mise en œuvre de mesures techniques et organisationnelles pour protéger les données. + +### 🔒 Mesures Techniques de Protection + +Conformément à la section [Sécurité](/docs/security), les mesures suivantes sont appliquées : +- **Chiffrement au repos** : Utilisation de **PGP (pgcrypto)** pour les données identifiantes. +- **Hachage aveugle** : Pour permettre les opérations sur données chiffrées sans compromettre la confidentialité. +- **Hachage des mots de passe** : Utilisation de l'algorithme **Argon2id**. +- **Communications sécurisées** : Utilisation de **TLS 1.3** via Caddy. + +### 👤 Droits des Utilisateurs + +Conformément au RGPD, les utilisateurs disposent des droits suivants, facilités par l'architecture technique : +- **Droit à l'effacement (droit à l'oubli)** : Mis en œuvre via un mécanisme de **Soft Delete** (`deleted_at`), suivi d'une purge définitive des données après un délai de conservation légal. +- **Droit d'accès et portabilité** : L'utilisation de schémas structurés (Drizzle/PostgreSQL) permet l'extraction facile des données d'un utilisateur sur demande. +- **Gestion du consentement** : Suivi rigoureux des versions de CGU et de politique de confidentialité acceptées (`terms_version`, `privacy_version`, `gdpr_accepted_at`). + +### ⏳ Conservation et Purge + +- **Purge Automatique** : Les données liées aux signalements (`reports`) disposent d'une date d'expiration (`expires_at`) pour garantir qu'elles ne sont pas conservées au-delà du nécessaire. +- **Anonymisation technique** : Les adresses IP stockées dans les tables `audit_logs` et `sessions` sont hachées (`ip_hash`), ce qui permet d'identifier des comportements malveillants tout en protégeant l'identité réelle de l'utilisateur. +- **Logs d'Audit** : Les journaux d'audit sont conservés pendant une période glissante pour répondre aux obligations de sécurité tout en respectant la minimisation. + +### 📍 Hébergement des Données + +Les données sont hébergées au sein de l'Union Européenne sur des serveurs dédiés chez **Hetzner**, garantissant un cadre juridique protecteur pour les données des citoyens européens. + +### 🔗 Références + +- [Site officiel de la CNIL](https://www.cnil.fr/fr/reglement-europeen-protection-donnees) +- [Texte officiel du RGPD](https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX%3A32016R0679) diff --git a/documentation/content/docs/database.mdx b/documentation/content/docs/database.mdx new file mode 100644 index 0000000..b9f0b12 --- /dev/null +++ b/documentation/content/docs/database.mdx @@ -0,0 +1,257 @@ +--- +title: Modèle de Données +description: Structure et organisation des données +--- + +## 📊 Modèle de Données + +### Conceptuel (MCD) + +Le Modèle Conceptuel de Données décrit les grandes entités du système et leurs relations métier, incluant la gestion des accès et la modération. + +```mermaid +erDiagram + USER ||--o{ CONTENT : "publie" + USER ||--o{ REPORT : "signale" + USER ||--o{ USER_ROLE : "possede" + USER ||--o{ SESSION : "detient" + USER ||--o{ API_KEY : "genere" + USER ||--o{ AUDIT_LOG : "genere" + + CONTENT ||--o{ CONTENT_TAG : "possede" + TAG ||--o{ CONTENT_TAG : "est_lie_a" + CONTENT ||--o{ REPORT : "est_signale" + TAG ||--o{ REPORT : "est_signale" + + ROLE ||--o{ USER_ROLE : "attribue_a" + ROLE ||--o{ ROLE_PERMISSION : "possede" + PERMISSION ||--o{ ROLE_PERMISSION : "est_lie_a" + + USER { + string username + string email + string display_name + string status + } + CONTENT { + string title + string type + string storage_key + } + TAG { + string name + string slug + } + ROLE { + string name + string slug + } + REPORT { + string reason + string status + } + SESSION { + string refresh_token + boolean is_valid + } + API_KEY { + string name + string prefix + boolean is_active + } + AUDIT_LOG { + string action + string entity_type + jsonb details + } +``` + +### Logique (MLD) + +Le Modèle Logique de Données précise les tables, les colonnes et les clés étrangères (FK). + +```mermaid +erDiagram + users { + uuid uuid PK + varchar username + bytea email + varchar email_hash + varchar display_name + varchar password_hash + user_status status + bytea two_factor_secret + boolean is_two_factor_enabled + varchar terms_version + varchar privacy_version + timestamp gdpr_accepted_at + timestamp last_login_at + timestamp created_at + timestamp updated_at + timestamp deleted_at + } + contents { + uuid id PK + uuid user_id FK + content_type type + varchar title + varchar storage_key + varchar mime_type + integer file_size + timestamp created_at + timestamp updated_at + timestamp deleted_at + } + tags { + uuid id PK + varchar name + varchar slug + timestamp created_at + timestamp updated_at + } + contents_to_tags { + uuid content_id PK, FK + uuid tag_id PK, FK + } + roles { + uuid id PK + varchar name + varchar slug + varchar description + timestamp created_at + } + permissions { + uuid id PK + varchar name + varchar slug + varchar description + timestamp created_at + } + roles_to_permissions { + uuid role_id PK, FK + uuid permission_id PK, FK + } + users_to_roles { + uuid user_id PK, FK + uuid role_id PK, FK + } + reports { + uuid id PK + uuid reporter_id FK + uuid content_id FK + uuid tag_id FK + report_reason reason + text description + report_status status + timestamp expires_at + timestamp created_at + timestamp updated_at + } + sessions { + uuid id PK + uuid user_id FK + varchar refresh_token + varchar user_agent + varchar ip_hash + boolean is_valid + timestamp expires_at + timestamp created_at + timestamp updated_at + } + api_keys { + uuid id PK + uuid user_id FK + varchar key_hash + varchar name + varchar prefix + boolean is_active + timestamp last_used_at + timestamp expires_at + timestamp created_at + timestamp updated_at + } + audit_logs { + uuid id PK + uuid user_id FK + varchar action + varchar entity_type + uuid entity_id + jsonb details + varchar ip_hash + varchar user_agent + timestamp created_at + } + + users ||--o{ contents : "user_id" + users ||--o{ users_to_roles : "user_id" + roles ||--o{ users_to_roles : "role_id" + roles ||--o{ roles_to_permissions : "role_id" + permissions ||--o{ roles_to_permissions : "permission_id" + contents ||--o{ contents_to_tags : "content_id" + tags ||--o{ contents_to_tags : "tag_id" + users ||--o{ reports : "reporter_id" + contents ||--o{ reports : "content_id" + tags ||--o{ reports : "tag_id" + users ||--o{ sessions : "user_id" + users ||--o{ api_keys : "user_id" + users ||--o{ audit_logs : "user_id" +``` + +### Physique (MPD) + +Le Modèle Physique de Données détaille l'implémentation spécifique pour **PostgreSQL**. + +```mermaid +erDiagram + users { + uuid uuid "DEFAULT gen_random_uuid()" + bytea email "ENCRYPTED, NOT NULL" + varchar email_hash "UNIQUE, INDEXED" + varchar username "UNIQUE, NOT NULL" + varchar password_hash "NOT NULL" + bytea two_factor_secret "ENCRYPTED" + boolean is_two_factor_enabled "DEFAULT false" + timestamp gdpr_accepted_at "NULLABLE" + timestamp deleted_at "SOFT DELETE" + } + contents { + uuid id "DEFAULT gen_random_uuid()" + uuid user_id "REFERENCES users(uuid)" + varchar storage_key "UNIQUE, NOT NULL" + integer file_size "NOT NULL" + timestamp deleted_at "SOFT DELETE" + } + reports { + uuid id "DEFAULT gen_random_uuid()" + uuid reporter_id "REFERENCES users(uuid)" + timestamp expires_at "RGPD PURGE" + } + api_keys { + uuid id "DEFAULT gen_random_uuid()" + varchar key_hash "UNIQUE, INDEXED, SHA-256" + varchar prefix "NOT NULL" + } + audit_logs { + uuid id "DEFAULT gen_random_uuid()" + jsonb details "STORED AS JSONB" + varchar ip_hash "RGPD COMPLIANT" + } + sessions { + uuid id "DEFAULT gen_random_uuid()" + varchar refresh_token "UNIQUE, NOT NULL" + varchar ip_hash "RGPD COMPLIANT" + } +``` + +#### Sécurité et Chiffrement +- **Chiffrement PGP (Native)** : Les colonnes `email` et `two_factor_secret` sont stockées au format `bytea` et chiffrées/déchiffrées via les fonctions `pgp_sym_encrypt` et `pgp_sym_decrypt` de PostgreSQL (via l'extension `pgcrypto`). +- **Hachage aveugle (Blind Indexing)** : La colonne `email_hash` stocke un hash (SHA-256) de l'email pour permettre les recherches d'unicité et les recherches rapides sans déchiffrer la donnée. + +#### Index et Optimisations +- **Index B-Tree** systématiques sur toutes les clés étrangères (`user_id`, `role_id`, etc.). +- **Index sur `deleted_at`** : Pour optimiser les requêtes excluant les données supprimées logiciellement. +- **Index unique sur `email_hash`** et `username`. + +#### Conformité RGPD +- **Soft Delete** : Implémenté via `deleted_at` pour permettre le "droit à l'oubli" tout en conservant l'intégrité référentielle temporaire. +- **Purge Automatique** : La colonne `expires_at` dans la table `reports` permet de programmer la suppression automatique des données de signalement après traitement. diff --git a/documentation/content/docs/deployment.mdx b/documentation/content/docs/deployment.mdx new file mode 100644 index 0000000..62fbf92 --- /dev/null +++ b/documentation/content/docs/deployment.mdx @@ -0,0 +1,18 @@ +--- +title: Déploiement & Tests +description: Procédures de déploiement et stratégie de tests +--- + +## 🚀 Déploiement + +### Architecture de service + +Un conteneur **Caddy** est utilisé en tant que reverse proxy pour fournir le TLS et la gestion du FQDN. + +### Pré-requis + +Liste des outils nécessaires (Node.js, pnpm, Docker). + +## 🧪 Tests + +- **Unitaires** : sur le backend diff --git a/documentation/content/docs/index.mdx b/documentation/content/docs/index.mdx index 1ede18e..8bfb46a 100644 --- a/documentation/content/docs/index.mdx +++ b/documentation/content/docs/index.mdx @@ -1,13 +1,42 @@ --- -title: Hello World -description: Your first document +title: Introduction +description: Détails techniques du projet Memegoat --- -Welcome to the docs! You can start writing documents in `/content/docs`. +# 🐐 Détails Techniques - Memegoat -## What is Next? +Ce document regroupe l'ensemble des spécifications techniques du projet Memegoat. - - - - +## 🏗️ Architecture Globale + +### Vue d'ensemble + +Description de l'architecture en monorepo et des interactions entre les services. + +### Diagrammes + +```mermaid +graph TD + User([Utilisateur]) + Caddy[Reverse Proxy: Caddy] + Frontend[Frontend: Next.js] + Backend[Backend: NestJS] + DB[(Database: PostgreSQL)] + Storage[Storage: S3 Compatible] + + User <--> Caddy + Caddy <--> Frontend + Caddy <--> Backend + Backend <--> DB + Backend <--> Storage +``` + +### Navigation + +Consultez les différentes sections pour plus de détails : +- [Stack Technologique](/docs/stack) +- [Modèle de Données](/docs/database) +- [Sécurité](/docs/security) +- [Conformité RGPD](/docs/compliance) +- [API & Intégrations](/docs/api) +- [Déploiement](/docs/deployment) diff --git a/documentation/content/docs/security.mdx b/documentation/content/docs/security.mdx new file mode 100644 index 0000000..6e65ee4 --- /dev/null +++ b/documentation/content/docs/security.mdx @@ -0,0 +1,26 @@ +--- +title: Sécurité +description: Mesures de sécurité implémentées +--- + +## 🔐 Sécurité + +### Protection des Données (At Rest) + +- **Chiffrement PGP Natif** : Les données identifiantes (PII) comme l'email, le nom d'affichage et le **secret 2FA** sont chiffrées dans PostgreSQL via `pgcrypto` (`pgp_sym_encrypt`). Les clés de déchiffrement ne sont jamais stockées en base de données. +- **Hachage aveugle (Blind Indexing)** : Pour permettre la recherche et l'unicité sur les données chiffrées (comme l'email), un hash non réversible (SHA-256) est stocké séparément (`email_hash`). +- **Hachage des mots de passe** : Utilisation d'**Argon2id** (via `@node-rs/argon2`), configuré selon les recommandations de l'ANSSI pour résister aux attaques par force brute et par table de correspondance. + +### Sécurité des Communications (In Transit) + +- **TLS 1.3** : Assuré par le reverse proxy **Caddy** avec renouvellement automatique des certificats Let's Encrypt. +- **Protocoles d'Authentification** : + - **Sessions (JWT)** : Les jetons de rafraîchissement (`refresh_token`) sont stockés de manière sécurisée en base de données. L'IP de l'utilisateur est hachée (`ip_hash`) pour concilier sécurité et respect de la vie privée. + - **API Keys** : Les clés API sont hachées en base de données (**SHA-256**) via la colonne `key_hash`. Seul un préfixe est conservé en clair pour l'identification. + +### Infrastructure & Défense + +- **Rate Limiting** : Protection contre le brute-force et le déni de service (DoS). +- **CORS Policy** : Restriction stricte des origines autorisées. +- **RBAC (Role Based Access Control)** : Gestion granulaire des permissions avec une structure complète de rôles et de permissions liées (`roles`, `permissions`, `roles_to_permissions`). +- **Audit Logs** : Traçabilité complète des actions sensibles via la table `audit_logs`. Elle enregistre l'action, l'entité concernée, les détails au format JSONB, ainsi que l'IP hachée et le User-Agent pour l'imputabilité. diff --git a/documentation/content/docs/stack.mdx b/documentation/content/docs/stack.mdx new file mode 100644 index 0000000..3f943ba --- /dev/null +++ b/documentation/content/docs/stack.mdx @@ -0,0 +1,27 @@ +--- +title: Stack Technologique +description: Technologies utilisées dans le projet Memegoat +--- + +## 🛠️ Stack Technologique + +### Frontend + +- **Framework** : NextJS +- **Gestion d'état** : Zustand +- **Style** : Tailwind CSS +- **Composants UI** : Shadcn/ui + +### Backend + +- **Framework** : NestJS +- **Langage** : TypeScript +- **Base de données** : PostgresQL +- **ORM** : DrizzleORM + +### Infrastructure & DevOps + +- **Conteneurisation** : Docker / Docker Compose +- **Reverse Proxy & TLS** : Caddy +- **CI/CD** : Gitea Actions +- **Hébergement** : Hetzner Dedicated Server