Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Contributing to RedactPDF

Merci pour ta contribution ❤️

## Objectif du projet

RedactPDF vise un caviardage PDF **réellement destructif** (sur l’export), avec audit post-traitement.

## Principes de contribution

1. **Priorité sécurité**
- Toute modif qui peut impacter la suppression réelle des données doit être testée.
2. **Ne pas casser l’audit**
- Si l’audit échoue, l’export ne doit pas être livré comme succès.
3. **Reproductibilité**
- Favoriser des fixtures déterministes et des tests automatisés.

## Setup local

### Backend
```bash
pip install -e "backend[dev]"
cd backend
uvicorn app.main:app --reload
```

### Frontend
```bash
cd frontend
npm install
npm run dev
```

## Tests

Voir [docs/TESTING.md](docs/TESTING.md).

En bref:
```bash
cd backend
pytest
ruff check .
```

Frontend:
```bash
cd frontend
npm run build
```

## Pull requests

Merci d’inclure dans la PR:

- **Contexte**: problème observé / besoin métier
- **Solution**: ce qui change techniquement
- **Impact sécurité**: texte/images/graphics/metadata/annotations/attachments
- **Validation**: commandes et résultats
- **Limites** éventuelles

## Zones sensibles (à relire attentivement)

- `backend/app/redaction.py`
- `backend/app/audit.py` et pipeline associé
- `frontend/src/components/PdfViewer.tsx`
- `frontend/src/api.ts`

## Bonnes pratiques produit

- Préférer des comportements explicitement “strict” pour les usages sensibles
- Documenter clairement les limites (PDF aplatis, scans, OCR, etc.)
- Éviter les promesses de sécurité non vérifiées
177 changes: 160 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,178 @@
# RedactPDF
Local, verifiable PDF redaction (removes content instead of masking).

## Backend
Outil de caviardage PDF **local et vérifiable** : l’objectif est de **retirer réellement** les données sensibles d’un PDF exporté, et pas seulement de les masquer visuellement.

Install dev dependencies:
```bash
pip install -e "backend[dev]"
```
---

## Pourquoi ce projet ?

Le mot “censure PDF” peut vouloir dire plusieurs choses très différentes en pratique.

- **Masquage visuel (overlay / rectangle noir dessiné)**
- On voit du noir à l’écran.
- Mais le texte, l’image ou l’objet d’origine peut rester récupérable.
- **Aplatissement / rasterisation**
- On convertit la page en image (ou en forme “figée”).
- Peut réduire la récupérabilité du texte, mais dégrade souvent la qualité et l’accessibilité.
- **Caviardage réel (redaction)**
- Le contenu ciblé est supprimé de la structure PDF exportée.
- C’est le mode visé par RedactPDF.

RedactPDF suit une approche “sécurité d’abord” : appliquer la redaction, puis auditer le résultat avant de livrer le PDF exporté.

---

## Fonctionnalités actuelles

### Censure par requêtes
- Recherche exacte
- Regex
- Options de matching (casse, sous-mot/mot entier, accents, etc.)

### Presets
- Emails
- Téléphones
- Cartes bancaires

### Censure visuelle guidée
- Sélection texte au curseur
- Censure de page complète
- Dessin de rectangles (click-glisser)

Run tests:
### Prévisualisation
- Surcouches de preview avant export
- Numérotation des rectangles dessinés pour faciliter le contrôle opérateur

### Durcissement de l’export
- Audit post-redaction (bloque la sortie si fuite détectée)
- Support options de sanitation (métadonnées, annotations, pièces jointes) selon configuration

---

## Limites connues (importantes)

1. **PDF “aplatis” / scans / pages-image**
- Si le document est essentiellement une image, les stratégies de redaction fine sont plus limitées.
- Dans certains scénarios, un rectangle qui chevauche une image peut conduire à retirer un objet image entier (si mode strict), ou à un masquage partiel visuel (si mode non strict).

2. **Censure partielle irréversible d’image/vectoriel (fine-grain)**
- Pas encore implémentée comme workflow natif robuste.
- Aujourd’hui, on est plutôt sur des modes “supprimer l’objet touché” vs “ne pas le supprimer”, selon options.

3. **OCR hors périmètre de base**
- Le pipeline de base ne reconstruit pas automatiquement du texte OCR pour scans complexes.

---

## Démarrage rapide (développeurs)

### Prérequis
- Python 3.10+
- Node.js 20+
- npm

### 1) Cloner
```bash
cd backend
pytest
git clone <URL_DU_REPO>
cd RedactPDF
```

Run the API locally:

### 2) Backend
```bash
pip install -e "backend[dev]"
cd backend
uvicorn app.main:app --reload
```
Backend dispo sur `http://127.0.0.1:8000` (par défaut).

### 3) Frontend
Dans un second terminal:
```bash
cd frontend
npm install
npm run dev
```
Frontend dispo sur `http://127.0.0.1:5173` (ou port affiché par Vite).

---

## Utilisation (opérateur)

1. Charger un PDF.
2. Ajouter des règles (requêtes/regex/presets), ou utiliser:
- **Censurer la page**
- **Dessiner sélection** (rectangle)
- **Sélection texte**
3. Vérifier la preview.
4. Cliquer **Censurer et télécharger**.
5. Si audit KO: corriger les règles et recommencer.

---

## Installation via Docker (sans build local complexe)

Voir le guide détaillé: [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md).

Résumé:
- Construire les images backend+frontend,
- Exposer les ports,
- Lancer les services via `docker compose up -d`.

---

## Installation via installeur / exécutable (utilisateur non technique)

Voir le plan détaillé: [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md).

Résumé:
- Fournir un package “un clic” qui:
- embarque backend + frontend,
- démarre les services localement,
- ouvre automatiquement l’URL locale dans le navigateur.

---

## Médias de documentation (placeholders)

Tu peux déposer ici des captures/gifs/vidéos, puis les référencer dans ce README.

Exemples recommandés:

- `docs/media/01-upload-and-preview.gif`
- Montrer: chargement d’un PDF + preview.
- `docs/media/02-text-selection-redaction.gif`
- Montrer: sélection texte au curseur puis ajout de règle.
- `docs/media/03-draw-rectangle.gif`
- Montrer: bouton “Dessiner sélection”, click-glisser, apparition `Rectangle X (Page Y)`.
- `docs/media/04-full-page-redaction.gif`
- Montrer: “Censurer la page” + preview pleine page.
- `docs/media/05-audit-fail-example.png`
- Montrer: modal d’échec audit avec détails.
- `docs/media/06-audit-pass-download.png`
- Montrer: succès + téléchargement.

Tu pourras ensuite ajouter des sections du type:

```md
![Draw rectangle demo](docs/media/03-draw-rectangle.gif)
```

## Security
---

See [docs/SECURITY.md](docs/SECURITY.md).
## Roadmap / idées d’amélioration

## Fixtures
- Censure partielle **irréversible** d’image et de graphiques (sans supprimer l’objet entier)
- Import/export de listes de requêtes de censure (profils réutilisables)
- OCR avancé pour PDFs scannés
- Plus d’outils visuels (édition de rectangles, regroupement, templates)
- E2E tests de bout en bout sur workflows UI complets

See [backend/tests/fixtures/README.md](backend/tests/fixtures/README.md).
---

## Testing
## Documentation complémentaire

See [docs/TESTING.md](docs/TESTING.md).
- Sécurité: [docs/SECURITY.md](docs/SECURITY.md)
- Tests: [docs/TESTING.md](docs/TESTING.md)
- Contribution: [CONTRIBUTING.md](CONTRIBUTING.md)
- Déploiement / packaging: [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md)
- Fixtures PDF de test: [backend/tests/fixtures/README.md](backend/tests/fixtures/README.md)
4 changes: 4 additions & 0 deletions backend/app/redaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ def _tighten_rect_vertical(rect: pymupdf.Rect) -> pymupdf.Rect:
if h <= 0:
return rect

# Les zones volumineuses (ex: page complète) ne doivent pas être compressées verticalement.
if h > 24.0:
return rect

target = h * 0.60
if target < 3.0:
target = 3.0
Expand Down
29 changes: 29 additions & 0 deletions backend/tests/test_redact_rectangles.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,32 @@ def test_redaction_does_not_modify_original_fixture_on_disk() -> None:
after_bytes = SECRET_FIXTURE.read_bytes()
assert before_bytes == after_bytes, "Fixture PDF on disk must remain byte-identical"
assert SECRET in extract_text(after_bytes), "Original must still contain the secret"


@pytest.mark.integration
def test_redact_rectangles_full_page_rect_redacts_target() -> None:
pdf_in = SECRET_FIXTURE.read_bytes()
original_text = extract_text(pdf_in)
assert SECRET in original_text

doc = pymupdf.open(stream=pdf_in, filetype="pdf")
try:
page = doc[0]
bounds = page.rect
full_page_rect = {"page": 0, "x0": bounds.x0, "y0": bounds.y0, "x1": bounds.x1, "y1": bounds.y1}
finally:
doc.close()

payload = make_payload([full_page_rect], patterns=[SECRET])

resp = CLIENT.post(
"/redact/rectangles",
files={"file": ("input.pdf", pdf_in, "application/pdf")},
data={"payload": json.dumps(payload)},
)

assert resp.status_code == 200
assert resp.headers.get("x-redaction-audit-status") == "pass"

out_text = extract_text(resp.content)
assert SECRET not in out_text
Loading
Loading