feat: production deployment - full update with providers, admin, glossaries, pricing, tests
Major changes across backend, frontend, infrastructure: - Provider system with model selection (Google, DeepL, OpenAI, Ollama, Google Cloud) - Admin panel: user management, pricing, settings - Glossary system with CSV import/export - Subscription and tier quota management - Security hardening (rate limiting, API key auth, path traversal fixes) - Docker compose for dev, prod, and IONOS deployment - Alembic migrations for new tables - Frontend: dashboard, pricing page, landing page, i18n (en/fr) - Test suite and verification scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
985
_bmad-output/planning-artifacts/architecture.md
Normal file
985
_bmad-output/planning-artifacts/architecture.md
Normal file
@@ -0,0 +1,985 @@
|
||||
---
|
||||
stepsCompleted: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
inputDocuments:
|
||||
- prd.md
|
||||
- prd-validation-report.md
|
||||
- product-brief-office_translator-2026-02-18.md
|
||||
workflowType: 'architecture'
|
||||
project_name: 'office_translator'
|
||||
user_name: 'Sepehr'
|
||||
date: '2026-02-18'
|
||||
lastStep: 8
|
||||
status: 'complete'
|
||||
completedAt: '2026-02-19'
|
||||
---
|
||||
|
||||
# Architecture Decision Document
|
||||
|
||||
_This document builds collaboratively through step-by-step discovery. Sections are appended as we work through each architectural decision together._
|
||||
|
||||
## Project Context Analysis
|
||||
|
||||
### Requirements Overview
|
||||
|
||||
**Functional Requirements:**
|
||||
|
||||
| Catégorie | Count | Impact Architectural |
|
||||
|-----------|-------|---------------------|
|
||||
| Document Translation | FR1-FR8 | Cœur métier - module translation |
|
||||
| Format Preservation | FR9-FR16 | Critique - différenciateur produit |
|
||||
| User Management & Auth | FR17-FR22 | Module auth (JWT + API Keys) |
|
||||
| Subscription & Billing | FR23-FR28 | Module payment à refactorer |
|
||||
| API & Integration | FR29-FR35 | API REST versionnée /api/v1/ |
|
||||
| Webhooks | FR36-FR38, FR65-FR66 | Module webhooks (Fire & Forget) |
|
||||
| Admin Dashboard | FR39-FR45 | Module admin |
|
||||
| Web UI | FR46-FR49 | Frontend Next.js |
|
||||
| File Management | FR50-FR54 | Stockage éphémère /tmp |
|
||||
| Error Handling | FR55-FR57 | Cross-cutting concern |
|
||||
| Glossaries & Prompts | FR58-FR61 | **MVP Critique** - Justification abonnement Pro |
|
||||
| URL Ingestion | FR62-FR64 | Feature automation |
|
||||
|
||||
**Non-Functional Requirements:**
|
||||
|
||||
| Catégorie | NFRs | Décisions Architecturales Clés |
|
||||
|-----------|------|-------------------------------|
|
||||
| Performance | NFR1-NFR5 | Async processing, progress feedback < 500ms |
|
||||
| Security | NFR6-NFR11 | JWT + API Keys, HTTPS, secrets via env |
|
||||
| Reliability | NFR12-NFR14 | 0% HTTP 500, provider fallback, TTL cleanup |
|
||||
| Data Retention | NFR15-NFR17 | Zero retention, 60 min TTL, RGPD by design |
|
||||
| API Quality | NFR18-NFR21 | OpenAPI 3.0, JSON errors, rate limiting, versioning |
|
||||
|
||||
**Scale & Complexity:**
|
||||
|
||||
- Primary domain: Full-stack (Backend API + Frontend Web + Admin Dashboard)
|
||||
- Complexity level: Moyenne-Haute
|
||||
- Estimated architectural components: 5 modules
|
||||
|
||||
### Technical Constraints & Dependencies
|
||||
|
||||
| Contrainte | Description | Impact |
|
||||
|------------|-------------|--------|
|
||||
| Brownfield | Refonte de l'existant | Architecture monolithique modulaire |
|
||||
| Solo Developer | Une seule personne | Pas de microservices, dette technique zéro |
|
||||
| Payment Module | Existant à refactorer | Clean Architecture pour module payment |
|
||||
| Stockage | Local éphémère /tmp | Pas de S3 pour MVP |
|
||||
| Hébergement | Préférence UE | RGPD compliance |
|
||||
| LLM Providers | Multi-provider (Ollama, OpenAI, compatibles) | Abstraction provider avec fallback |
|
||||
|
||||
### Cross-Cutting Concerns Identified
|
||||
|
||||
| Concern | Modules Affectés | Stratégie |
|
||||
|---------|------------------|-----------|
|
||||
| Rate Limiting | API, Auth | Par utilisateur/tier, réponse 429 avec Retry-After |
|
||||
| Logging | Tous | Structuré, métadonnées uniquement (pas de contenu document) |
|
||||
| Error Handling | Tous | 0% HTTP 500, erreurs JSON structurées |
|
||||
| File Cleanup | Translation | TTL 60 min, hard delete après download |
|
||||
| Auth | API, Admin, Web | JWT (Web/Admin) + API Keys (Automation) |
|
||||
|
||||
## Starter Template Evaluation
|
||||
|
||||
### Primary Technology Domain
|
||||
|
||||
**Full-stack Brownfield** — Refonte de l'existant avec stack technologique validée.
|
||||
|
||||
### Contexte Projet
|
||||
|
||||
Ce n'est pas un projet greenfield. L'objectif est de **refactorer** une codebase existante vers une architecture propre (Clean Architecture) plutôt que de partir d'un starter template.
|
||||
|
||||
### Stack Technologique Confirmée
|
||||
|
||||
| Couche | Technologie | Justification |
|
||||
|--------|-------------|---------------|
|
||||
| **Backend** | FastAPI (Python) | Écosystème Python, async natif, excellent pour API REST |
|
||||
| **Frontend** | Next.js 15 (App Router) | Déjà en place, Tailwind CSS inclus |
|
||||
| **Base de données** | PostgreSQL (prod) / SQLite (dev) | SaaS-ready, données persistantes (users, subscriptions, API keys) |
|
||||
| **ORM** | SQLAlchemy / SQLModel | Moderne, typé, compatible FastAPI |
|
||||
| **Rate Limiting** | Redis | Robuste, distribué, performant |
|
||||
| **Déploiement** | Docker + VPS | Reverse proxy (Traefik/Nginx), HTTPS/HSTS |
|
||||
|
||||
### Refactoring Backend - Clean Architecture
|
||||
|
||||
**Structure cible par domaine:**
|
||||
|
||||
```
|
||||
backend/
|
||||
├── modules/
|
||||
│ ├── translation/ # Cœur métier
|
||||
│ │ ├── router.py
|
||||
│ │ ├── service.py
|
||||
│ │ └── schemas.py
|
||||
│ ├── auth/ # JWT + API Keys
|
||||
│ ├── payment/ # À refactorer
|
||||
│ ├── admin/ # Dashboard
|
||||
│ └── webhooks/ # Notifications
|
||||
├── core/
|
||||
│ ├── config.py # Pydantic BaseSettings
|
||||
│ ├── security.py
|
||||
│ └── database.py
|
||||
└── main.py # Point d'entrée épuré
|
||||
```
|
||||
|
||||
### Refactoring Frontend - Focus UX
|
||||
|
||||
- Suppression code mort
|
||||
- Amélioration Core Web Vitals (LCP < 2.5s, INP < 200ms, CLS < 0.1)
|
||||
- UX cohérente (textes unifiés, parcours clairs)
|
||||
|
||||
### Décisions Architecturales Établies
|
||||
|
||||
**Language & Runtime:**
|
||||
- Backend: Python 3.11+ avec FastAPI
|
||||
- Frontend: TypeScript avec Next.js 15
|
||||
|
||||
**Styling Solution:**
|
||||
- Tailwind CSS (déjà configuré)
|
||||
|
||||
**Build Tooling:**
|
||||
- Backend: uv/pip avec pyproject.toml
|
||||
- Frontend: Next.js built-in (Turbopack)
|
||||
|
||||
**Database & ORM:**
|
||||
- PostgreSQL (prod) / SQLite (dev)
|
||||
- SQLAlchemy 2.0 ou SQLModel
|
||||
|
||||
**Infrastructure:**
|
||||
- Docker Compose pour orchestration locale
|
||||
- VPS avec reverse proxy pour production
|
||||
|
||||
## Core Architectural Decisions
|
||||
|
||||
### Decision Priority Analysis
|
||||
|
||||
**Critical Decisions (Block Implementation):**
|
||||
- Auth library (PyJWT)
|
||||
- Database migrations (Alembic)
|
||||
- Error format (JSON structuré)
|
||||
|
||||
**Important Decisions (Shape Architecture):**
|
||||
- State management frontend (TanStack Query)
|
||||
- Logging (structlog)
|
||||
- API documentation (Swagger + ReDoc)
|
||||
|
||||
**Deferred Decisions (Post-MVP):**
|
||||
- Prometheus/Grafana monitoring
|
||||
- Zustand pour state local complexe
|
||||
|
||||
### Data Architecture
|
||||
|
||||
| Décision | Choix | Version | Rationale |
|
||||
|----------|-------|---------|-----------|
|
||||
| Database | PostgreSQL (prod) / SQLite (dev) | 16+ / 3.x | SaaS-ready, abonnements, API keys |
|
||||
| ORM | SQLAlchemy 2.0 / SQLModel | 2.0+ | Typé, compatible FastAPI, mature |
|
||||
| Migrations | **Alembic** | Latest | Standard absolu SQLAlchemy, évolutivité schéma |
|
||||
| Validation | Pydantic v2 | 2.x | Natif FastAPI, validation automatique |
|
||||
|
||||
### Authentication & Security
|
||||
|
||||
| Décision | Choix | Version | Rationale |
|
||||
|----------|-------|---------|-----------|
|
||||
| JWT Library | **PyJWT** | 2.x | Moderne, bien maintenu, plus standard que python-jose |
|
||||
| Password Hashing | **passlib[bcrypt]** | Latest | Éprouvé, standard industrie, parfait MVP |
|
||||
| API Key Generation | **secrets.token_urlsafe(32)** | Natif | 256-bit, URL-safe, simple, sécurisé |
|
||||
| Token Expiry | Access: 15min, Refresh: 7 days | — | PRD NFR6 |
|
||||
|
||||
**Flux Auth:**
|
||||
```
|
||||
Web/Admin → JWT (Access + Refresh Tokens)
|
||||
API Automation → X-API-Key header (static key)
|
||||
```
|
||||
|
||||
### API & Communication Patterns
|
||||
|
||||
| Décision | Choix | Rationale |
|
||||
|----------|-------|-----------|
|
||||
| REST Versioning | `/api/v1/` | PRD requirement, préserve intégrations |
|
||||
| Error Format | `{error, message, details?}` | Parsable par n8n, clair pour devs |
|
||||
| Documentation | **Swagger UI + ReDoc** | FastAPI génère gratuitement, Swagger=test, ReDoc=lecture |
|
||||
| Rate Limiting | Redis + sliding window | Par utilisateur/tier, réponse 429 + Retry-After |
|
||||
|
||||
**Endpoints Principaux:**
|
||||
| Endpoint | Méthode | Description |
|
||||
|----------|---------|-------------|
|
||||
| `/api/v1/translate` | POST | Traduire un document |
|
||||
| `/api/v1/languages` | GET | Langues supportées |
|
||||
| `/api/v1/health` | GET | Santé du service |
|
||||
| `/api/v1/download/{id}` | GET | Télécharger fichier traduit |
|
||||
|
||||
### Frontend Architecture
|
||||
|
||||
| Décision | Choix | Rationale |
|
||||
|----------|-------|-----------|
|
||||
| State Management (Server) | **TanStack Query** | Standard pour appels API Next.js, cache, revalidation |
|
||||
| State Management (Local) | React useState | Suffisant pour UI state, pas de Zustand nécessaire |
|
||||
| Component Model | Server Components default | Next.js 15 best practice, 'use client' si besoin |
|
||||
| Styling | Tailwind CSS | Déjà configuré |
|
||||
|
||||
**Pattern Data Fetching:**
|
||||
```tsx
|
||||
// Server Component (default)
|
||||
const data = await fetch('/api/v1/languages');
|
||||
|
||||
// Client Component avec TanStack Query
|
||||
const { data, isLoading } = useQuery({ queryKey: ['translations'], ... });
|
||||
```
|
||||
|
||||
### Infrastructure & Deployment
|
||||
|
||||
| Décision | Choix | Rationale |
|
||||
|----------|-------|-----------|
|
||||
| Logging | **structlog** | JSON structuré, lisible par Admin Dashboard |
|
||||
| Monitoring | **Simple health checks** | GET /health existant, pas d'over-engineering |
|
||||
| Containerization | Docker Compose | Backend + Frontend + Redis + DB |
|
||||
| Reverse Proxy | Traefik ou Nginx | HTTPS/HSTS, termination SSL |
|
||||
| Hosting | VPS unique | Solo dev, simple, coût maîtrisé |
|
||||
|
||||
**Health Check Format:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"database": "connected",
|
||||
"redis": "connected",
|
||||
"providers": {"google": "ok", "deepl": "ok"}
|
||||
}
|
||||
```
|
||||
|
||||
### Decision Impact Analysis
|
||||
|
||||
**Séquence d'Implémentation:**
|
||||
1. Setup Alembic migrations
|
||||
2. Core: Auth module (PyJWT + passlib)
|
||||
3. Core: Translation module (providers abstraction)
|
||||
4. API: REST endpoints + error format
|
||||
5. Frontend: TanStack Query setup
|
||||
6. Infra: structlog integration
|
||||
7. Admin: Dashboard health metrics
|
||||
|
||||
**Cross-Component Dependencies:**
|
||||
- Auth → DB (users, api_keys tables)
|
||||
- Translation → Redis (rate limiting, progress)
|
||||
- Admin → Logging (structlog consumption)
|
||||
- Webhooks → Translation (completion events)
|
||||
|
||||
## Implementation Patterns & Consistency Rules
|
||||
|
||||
### ⚠️ Règles Critiques (Non-Négociables)
|
||||
|
||||
Ces règles DOIVENT être respectées par tous les agents AI pour éviter les conflits:
|
||||
|
||||
```
|
||||
🚨 NEXT.JS APP ROUTER - FICHIERS SPÉCIAUX
|
||||
page.tsx, layout.tsx, route.ts, loading.tsx, error.tsx
|
||||
→ TOUJOURS en minuscules strictes
|
||||
→ JAMAIS PascalCase (le framework plantera avec 404)
|
||||
```
|
||||
|
||||
### Naming Patterns
|
||||
|
||||
#### Backend (Python/FastAPI)
|
||||
|
||||
| Élément | Convention | Exemple |
|
||||
|---------|------------|---------|
|
||||
| Tables DB | snake_case, pluriel | `users`, `api_keys`, `translations` |
|
||||
| Colonnes DB | snake_case | `user_id`, `created_at`, `file_name` |
|
||||
| Foreign keys | `{table}_id` | `user_id`, `subscription_id` |
|
||||
| Index | `idx_{table}_{columns}` | `idx_users_email`, `idx_translations_user_id` |
|
||||
| Fichiers Python | snake_case | `translation_service.py`, `auth_router.py` |
|
||||
| Variables | snake_case | `user_id`, `file_path`, `translation_result` |
|
||||
| Fonctions | snake_case | `get_user_by_id()`, `translate_document()` |
|
||||
| Classes | PascalCase | `TranslationService`, `UserRepository` |
|
||||
| Constantes | UPPER_SNAKE | `MAX_FILE_SIZE`, `TTL_SECONDS`, `API_VERSION` |
|
||||
|
||||
#### Frontend (TypeScript/Next.js)
|
||||
|
||||
| Élément | Convention | Exemple |
|
||||
|---------|------------|---------|
|
||||
| **Fichiers spéciaux App Router** | **minuscules strictes** | `page.tsx`, `layout.tsx`, `route.ts`, `loading.tsx`, `error.tsx` |
|
||||
| Composants réutilisables | PascalCase | `UserCard.tsx`, `TranslationProgress.tsx` |
|
||||
| Utilitaires/lib | camelCase | `apiClient.ts`, `formatters.ts` |
|
||||
| Variables | camelCase | `userId`, `fileName`, `translationResult` |
|
||||
| Fonctions | camelCase | `getUserById()`, `handleFileUpload()` |
|
||||
| Composants (nom) | PascalCase | `<UserCard />`, `<TranslationProgress />` |
|
||||
| Hooks | useCamelCase | `useTranslation()`, `useUser()` |
|
||||
| Types/Interfaces | PascalCase | `User`, `TranslationResponse`, `ApiError` |
|
||||
|
||||
#### API (Communication Backend ↔ Frontend)
|
||||
|
||||
| Élément | Convention | Exemple |
|
||||
|---------|------------|---------|
|
||||
| Endpoints REST | pluriel, kebab-case | `/api/v1/users`, `/api/v1/api-keys` |
|
||||
| Paramètres route | snake_case | `/api/v1/translations/{translation_id}` |
|
||||
| Query params | snake_case | `?user_id=123&file_type=xlsx` |
|
||||
| Headers | Pascal-Kebab | `X-API-Key`, `Content-Type`, `Authorization` |
|
||||
| **JSON fields** | **snake_case** | `user_id`, `created_at`, `file_name` |
|
||||
| Dates | ISO 8601 string | `"2024-01-15T10:30:00Z"` |
|
||||
|
||||
### API Response Formats
|
||||
|
||||
#### Format Succès
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": "abc123",
|
||||
"file_name": "report.xlsx",
|
||||
"status": "completed"
|
||||
},
|
||||
"meta": {
|
||||
"rate_limit_remaining": 45,
|
||||
"provider_used": "google",
|
||||
"processing_time_ms": 2340
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Champ `meta` utilisé pour:**
|
||||
- Rate limiting info (`rate_limit_remaining`, `rate_limit_reset`)
|
||||
- Pagination (`page`, `per_page`, `total`)
|
||||
- Provider info (`provider_used`)
|
||||
- Performance (`processing_time_ms`)
|
||||
|
||||
#### Format Erreur
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "QUOTA_EXCEEDED",
|
||||
"message": "Limite quotidienne atteinte. Passez en Pro pour plus de traductions.",
|
||||
"details": {
|
||||
"current_usage": 5,
|
||||
"limit": 5,
|
||||
"reset_at": "2024-01-16T00:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**⚠️ Pas de champ `data` en cas d'erreur.**
|
||||
|
||||
#### Codes Erreur Standards
|
||||
|
||||
| Code | HTTP | Usage |
|
||||
|------|------|-------|
|
||||
| `INVALID_FORMAT` | 400 | Format fichier non supporté |
|
||||
| `QUOTA_EXCEEDED` | 429 | Limite tier atteinte |
|
||||
| `UNAUTHORIZED` | 401 | Token/API key invalide |
|
||||
| `FORBIDDEN` | 403 | Pas les droits |
|
||||
| `FILE_TOO_LARGE` | 413 | Fichier > max size |
|
||||
| `PROVIDER_ERROR` | 502 | Provider externe en erreur |
|
||||
|
||||
### Structure Patterns
|
||||
|
||||
#### Organisation Tests
|
||||
|
||||
| Couche | Emplacement | Exemple |
|
||||
|--------|-------------|---------|
|
||||
| Backend (Python) | `tests/` centralisé | `tests/test_translation_service.py` |
|
||||
| Frontend (TS/React) | Co-localisé | `components/UserCard.test.tsx` |
|
||||
|
||||
#### Organisation Frontend (Colocation Pattern)
|
||||
|
||||
```
|
||||
frontend/src/
|
||||
├── app/ # Next.js App Router
|
||||
│ ├── (auth)/ # Route group
|
||||
│ │ └── login/
|
||||
│ │ ├── page.tsx # ⚠️ minuscule!
|
||||
│ │ ├── LoginForm.tsx # ⭐ Colocated component
|
||||
│ │ └── types.ts # ⭐ Colocated types
|
||||
│ ├── dashboard/
|
||||
│ │ └── translate/
|
||||
│ │ ├── page.tsx
|
||||
│ │ ├── FileUploader.tsx # ⭐ Colocated
|
||||
│ │ ├── useTranslation.ts # ⭐ Colocated hook
|
||||
│ │ └── types.ts
|
||||
│ ├── layout.tsx
|
||||
│ └── page.tsx
|
||||
├── components/
|
||||
│ └── ui/ # ⭐ Seulement composants GLOBAUX
|
||||
│ ├── Button.tsx
|
||||
│ └── Input.tsx
|
||||
├── lib/ # ⭐ Seulement utilitaires GLOBAUX
|
||||
│ └── apiClient.ts
|
||||
└── providers/
|
||||
└── QueryProvider.tsx
|
||||
```
|
||||
|
||||
### Process Patterns
|
||||
|
||||
#### Error Handling
|
||||
|
||||
**Backend:**
|
||||
```python
|
||||
from fastapi import HTTPException
|
||||
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail={
|
||||
"error": "INVALID_FORMAT",
|
||||
"message": "Format PDF non supporté",
|
||||
"details": {"accepted_formats": [".xlsx", ".docx", ".pptx"]}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
**Frontend:**
|
||||
```typescript
|
||||
try {
|
||||
const result = await apiClient.translate(file);
|
||||
} catch (error) {
|
||||
// error.response.data = { error, message, details }
|
||||
toast.error(error.response.data.message);
|
||||
}
|
||||
```
|
||||
|
||||
#### Loading States
|
||||
|
||||
```typescript
|
||||
// TanStack Query pattern
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: ['translation', id],
|
||||
queryFn: () => apiClient.getTranslation(id),
|
||||
});
|
||||
|
||||
if (isLoading) return <LoadingSpinner />;
|
||||
if (error) return <ErrorMessage error={error} />;
|
||||
return <TranslationResult data={data} />;
|
||||
```
|
||||
|
||||
### Enforcement Guidelines
|
||||
|
||||
**Tous les agents AI DOIVENT:**
|
||||
|
||||
1. ✅ Respecter les conventions de nommage par langage
|
||||
2. ✅ Utiliser les formats API définis (succès avec `data`+`meta`, erreur sans `data`)
|
||||
3. ✅ Nommer les fichiers spéciaux Next.js en minuscules (`page.tsx`, pas `Page.tsx`)
|
||||
4. ✅ Utiliser snake_case pour les champs JSON API
|
||||
5. ✅ Retourner des erreurs structurées avec codes explicites
|
||||
6. ✅ Placer les tests selon les conventions (centralisé Python, co-localisé TS)
|
||||
|
||||
**Anti-Patterns à ÉVITER:**
|
||||
|
||||
```typescript
|
||||
// ❌ MAUVAIS - Fichier App Router en PascalCase
|
||||
app/Dashboard/Page.tsx // → 404 error!
|
||||
|
||||
// ❌ MAUVAIS - camelCase dans JSON API
|
||||
{ "fileName": "report.xlsx" }
|
||||
|
||||
// ❌ MAUVAIS - data présent dans erreur
|
||||
{ "data": null, "error": "..." }
|
||||
|
||||
// ✅ BON
|
||||
app/dashboard/page.tsx
|
||||
{ "file_name": "report.xlsx" }
|
||||
{ "error": "...", "message": "..." } // pas de data
|
||||
```
|
||||
|
||||
### Pattern Examples
|
||||
|
||||
**Exemple Requête API Complète:**
|
||||
|
||||
```http
|
||||
POST /api/v1/translate
|
||||
X-API-Key: sk_live_abc123...
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
file: report.xlsx
|
||||
source_lang: en
|
||||
target_lang: fr
|
||||
webhook_url: https://example.com/webhook
|
||||
```
|
||||
|
||||
**Réponse Succès:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": "tr_abc123",
|
||||
"status": "processing",
|
||||
"file_name": "report.xlsx",
|
||||
"source_lang": "en",
|
||||
"target_lang": "fr"
|
||||
},
|
||||
"meta": {
|
||||
"rate_limit_remaining": 49,
|
||||
"estimated_time_seconds": 12
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Réponse Erreur:**
|
||||
```json
|
||||
{
|
||||
"error": "QUOTA_EXCEEDED",
|
||||
"message": "Limite quotidienne atteinte (5/5 fichiers)",
|
||||
"details": {
|
||||
"current_usage": 5,
|
||||
"limit": 5,
|
||||
"tier": "free",
|
||||
"reset_at": "2024-01-16T00:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Project Structure & Boundaries
|
||||
|
||||
### ⚠️ Règle de Colocation (Frontend)
|
||||
|
||||
```
|
||||
🚨 NEXT.JS APP ROUTER - COLOCATION
|
||||
Les composants, hooks et types spécifiques à une page
|
||||
doivent vivre DANS le dossier de la route correspondante.
|
||||
|
||||
→ Un seul dossier par feature = tous les fichiers proches
|
||||
→ Seuls les composants GLOBAUX vont dans src/components/ui/
|
||||
```
|
||||
|
||||
### Complete Project Directory Structure
|
||||
|
||||
```
|
||||
office_translator/
|
||||
├── docker-compose.yml
|
||||
├── docker-compose.dev.yml
|
||||
├── .env.example
|
||||
├── .gitignore
|
||||
├── README.md
|
||||
│
|
||||
├── backend/
|
||||
│ ├── pyproject.toml
|
||||
│ ├── requirements.txt
|
||||
│ ├── alembic.ini
|
||||
│ ├── .env.example
|
||||
│ ├── Dockerfile
|
||||
│ │
|
||||
│ ├── alembic/
|
||||
│ │ ├── env.py
|
||||
│ │ ├── versions/
|
||||
│ │ │ ├── 001_initial_users.py # User + tier field
|
||||
│ │ │ ├── 002_api_keys.py
|
||||
│ │ │ ├── 003_translations.py
|
||||
│ │ │ └── 004_glossaries.py
|
||||
│ │ └── script.py.mako
|
||||
│ │
|
||||
│ ├── app/
|
||||
│ │ ├── main.py
|
||||
│ │ ├── __init__.py
|
||||
│ │ │
|
||||
│ │ ├── core/
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── config.py # Pydantic BaseSettings
|
||||
│ │ │ ├── database.py # SQLAlchemy async engine
|
||||
│ │ │ ├── security.py # JWT, password hashing
|
||||
│ │ │ ├── logging.py # structlog setup
|
||||
│ │ │ └── exceptions.py # Custom exceptions
|
||||
│ │ │
|
||||
│ │ ├── modules/
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ │
|
||||
│ │ │ ├── auth/
|
||||
│ │ │ │ ├── __init__.py
|
||||
│ │ │ │ ├── router.py # /api/v1/auth/*
|
||||
│ │ │ │ ├── service.py
|
||||
│ │ │ │ ├── schemas.py
|
||||
│ │ │ │ └── dependencies.py # get_current_user
|
||||
│ │ │ │
|
||||
│ │ │ ├── translation/
|
||||
│ │ │ │ ├── __init__.py
|
||||
│ │ │ │ ├── router.py # /api/v1/translate
|
||||
│ │ │ │ ├── service.py # Translation orchestration
|
||||
│ │ │ │ ├── ingest.py # ⭐ URL ingestion (FR62-FR64)
|
||||
│ │ │ │ ├── schemas.py
|
||||
│ │ │ │ ├── providers/
|
||||
│ │ │ │ │ ├── __init__.py
|
||||
│ │ │ │ │ ├── base.py # Abstract provider
|
||||
│ │ │ │ │ ├── google.py
|
||||
│ │ │ │ │ ├── deepl.py
|
||||
│ │ │ │ │ ├── ollama.py
|
||||
│ │ │ │ │ └── openai.py
|
||||
│ │ │ │ └── processors/
|
||||
│ │ │ │ ├── __init__.py
|
||||
│ │ │ │ ├── excel.py
|
||||
│ │ │ │ ├── word.py
|
||||
│ │ │ │ └── powerpoint.py
|
||||
│ │ │ │
|
||||
│ │ │ ├── glossaries/
|
||||
│ │ │ │ ├── __init__.py
|
||||
│ │ │ │ ├── router.py # /api/v1/glossaries
|
||||
│ │ │ │ ├── service.py
|
||||
│ │ │ │ └── schemas.py
|
||||
│ │ │ │
|
||||
│ │ │ ├── webhooks/
|
||||
│ │ │ │ ├── __init__.py
|
||||
│ │ │ │ ├── router.py
|
||||
│ │ │ │ ├── service.py # ⭐ Fire & Forget (FR36-FR38)
|
||||
│ │ │ │ └── schemas.py
|
||||
│ │ │ │
|
||||
│ │ │ ├── admin/
|
||||
│ │ │ │ ├── __init__.py
|
||||
│ │ │ │ ├── router.py # /api/v1/admin/*
|
||||
│ │ │ │ ├── service.py
|
||||
│ │ │ │ └── schemas.py
|
||||
│ │ │ │
|
||||
│ │ │ └── payment/
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── router.py # /api/v1/payments
|
||||
│ │ │ ├── service.py
|
||||
│ │ │ └── schemas.py
|
||||
│ │ │
|
||||
│ │ ├── models/
|
||||
│ │ │ ├── __init__.py
|
||||
│ │ │ ├── user.py # ⭐ user.tier (free/pro) direct
|
||||
│ │ │ ├── api_key.py
|
||||
│ │ │ ├── translation.py
|
||||
│ │ │ └── glossary.py
|
||||
│ │ │
|
||||
│ │ └── middleware/
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── rate_limit.py # Redis + user.tier check
|
||||
│ │ └── error_handler.py
|
||||
│ │
|
||||
│ └── tests/
|
||||
│ ├── __init__.py
|
||||
│ ├── conftest.py
|
||||
│ ├── test_translation_service.py
|
||||
│ ├── test_ingest.py # ⭐ URL ingestion tests
|
||||
│ ├── test_auth_router.py
|
||||
│ ├── test_rate_limit.py
|
||||
│ └── test_providers/
|
||||
│ ├── test_google_provider.py
|
||||
│ └── test_deepl_provider.py
|
||||
│
|
||||
├── frontend/
|
||||
│ ├── package.json
|
||||
│ ├── next.config.js
|
||||
│ ├── tailwind.config.ts
|
||||
│ ├── tsconfig.json
|
||||
│ ├── .env.local.example
|
||||
│ ├── Dockerfile
|
||||
│ │
|
||||
│ ├── src/
|
||||
│ │ ├── app/
|
||||
│ │ │ ├── layout.tsx # Root layout
|
||||
│ │ │ ├── page.tsx # Landing page
|
||||
│ │ │ ├── globals.css
|
||||
│ │ │ │
|
||||
│ │ │ ├── (auth)/
|
||||
│ │ │ │ ├── layout.tsx
|
||||
│ │ │ │ ├── login/
|
||||
│ │ │ │ │ ├── page.tsx
|
||||
│ │ │ │ │ ├── LoginForm.tsx # ⭐ Colocated
|
||||
│ │ │ │ │ └── types.ts # ⭐ Colocated
|
||||
│ │ │ │ └── register/
|
||||
│ │ │ │ ├── page.tsx
|
||||
│ │ │ │ ├── RegisterForm.tsx # ⭐ Colocated
|
||||
│ │ │ │ └── types.ts
|
||||
│ │ │ │
|
||||
│ │ │ ├── dashboard/
|
||||
│ │ │ │ ├── layout.tsx
|
||||
│ │ │ │ ├── page.tsx
|
||||
│ │ │ │ ├── translate/
|
||||
│ │ │ │ │ ├── page.tsx
|
||||
│ │ │ │ │ ├── FileUploader.tsx # ⭐ Colocated
|
||||
│ │ │ │ │ ├── TranslationProgress.tsx
|
||||
│ │ │ │ │ ├── LanguageSelector.tsx
|
||||
│ │ │ │ │ ├── useTranslation.ts # ⭐ Colocated hook
|
||||
│ │ │ │ │ └── types.ts # ⭐ Colocated types
|
||||
│ │ │ │ ├── api-keys/
|
||||
│ │ │ │ │ ├── page.tsx
|
||||
│ │ │ │ │ ├── ApiKeyManager.tsx # ⭐ Colocated
|
||||
│ │ │ │ │ ├── useApiKeys.ts
|
||||
│ │ │ │ │ └── types.ts
|
||||
│ │ │ │ └── glossaries/
|
||||
│ │ │ │ ├── page.tsx
|
||||
│ │ │ │ ├── GlossaryEditor.tsx # ⭐ Colocated
|
||||
│ │ │ │ ├── useGlossaries.ts
|
||||
│ │ │ │ └── types.ts
|
||||
│ │ │ │
|
||||
│ │ │ └── admin/
|
||||
│ │ │ ├── layout.tsx
|
||||
│ │ │ ├── page.tsx
|
||||
│ │ │ ├── users/
|
||||
│ │ │ │ ├── page.tsx
|
||||
│ │ │ │ ├── UserTable.tsx # ⭐ Colocated
|
||||
│ │ │ │ ├── TierBadge.tsx
|
||||
│ │ │ │ └── types.ts
|
||||
│ │ │ └── system/
|
||||
│ │ │ ├── page.tsx
|
||||
│ │ │ ├── HealthStatus.tsx # ⭐ Colocated
|
||||
│ │ │ └── types.ts
|
||||
│ │ │
|
||||
│ │ ├── components/
|
||||
│ │ │ └── ui/ # ⭐ Seulement composants GLOBAUX
|
||||
│ │ │ ├── Button.tsx
|
||||
│ │ │ ├── Input.tsx
|
||||
│ │ │ ├── Card.tsx
|
||||
│ │ │ ├── Modal.tsx
|
||||
│ │ │ ├── LoadingSpinner.tsx
|
||||
│ │ │ └── ErrorMessage.tsx
|
||||
│ │ │
|
||||
│ │ ├── lib/ # ⭐ Seulement utilitaires GLOBAUX
|
||||
│ │ │ ├── apiClient.ts # Fetch wrapper, error handling
|
||||
│ │ │ ├── auth.ts # Token management
|
||||
│ │ │ └── constants.ts # App-wide constants
|
||||
│ │ │
|
||||
│ │ └── providers/
|
||||
│ │ └── QueryProvider.tsx # TanStack Query setup
|
||||
│ │
|
||||
│ ├── __tests__/
|
||||
│ │ └── lib/
|
||||
│ │ └── apiClient.test.ts
|
||||
│ │
|
||||
│ └── public/
|
||||
│ ├── favicon.ico
|
||||
│ └── logo.svg
|
||||
│
|
||||
└── scripts/
|
||||
├── deploy.sh
|
||||
└── backup-db.sh
|
||||
```
|
||||
|
||||
### Architectural Boundaries
|
||||
|
||||
#### API Boundaries
|
||||
|
||||
| Frontière | Description |
|
||||
|-----------|-------------|
|
||||
| `/api/v1/translate` | Public endpoint (auth required) |
|
||||
| `/api/v1/admin/*` | Admin-only (role check) |
|
||||
| `/api/v1/glossaries` | Pro-only (tier check) |
|
||||
| Rate Limiting | Middleware → Redis → user.tier |
|
||||
|
||||
#### Data Boundaries
|
||||
|
||||
**Modèle User (simplifié pour Rate Limiting):**
|
||||
|
||||
```python
|
||||
# models/user.py
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id: Mapped[UUID]
|
||||
email: Mapped[str]
|
||||
hashed_password: Mapped[str]
|
||||
tier: Mapped[str] = mapped_column(default="free") # ⭐ "free" | "pro"
|
||||
daily_translation_count: Mapped[int] = mapped_column(default=0)
|
||||
# ... timestamps
|
||||
```
|
||||
|
||||
**Rate Limiting Logic:**
|
||||
```python
|
||||
# middleware/rate_limit.py
|
||||
FREE_TIER_LIMIT = 5 # files per day
|
||||
PRO_TIER_LIMIT = None # unlimited
|
||||
|
||||
if user.tier == "free" and user.daily_translation_count >= FREE_TIER_LIMIT:
|
||||
raise QuotaExceededError()
|
||||
```
|
||||
|
||||
### Requirements to Structure Mapping
|
||||
|
||||
| Module PRD | Backend | Frontend |
|
||||
|------------|---------|----------|
|
||||
| Translation (FR1-FR8) | `modules/translation/` | `app/dashboard/translate/` |
|
||||
| Format Preservation (FR9-FR16) | `modules/translation/processors/` | — |
|
||||
| URL Ingestion (FR62-FR64) | `modules/translation/ingest.py` | — |
|
||||
| Auth (FR17-FR22) | `modules/auth/` | `app/(auth)/` |
|
||||
| Payment (FR23-FR28) | `modules/payment/` | `app/dashboard/` |
|
||||
| API Keys (FR29-FR31) | `models/api_key.py` | `app/dashboard/api-keys/` |
|
||||
| Webhooks (FR36-FR38) | `modules/webhooks/` | — |
|
||||
| Admin (FR39-FR45) | `modules/admin/` | `app/admin/` |
|
||||
| Glossaries (FR58-FR61) | `modules/glossaries/` | `app/dashboard/glossaries/` |
|
||||
|
||||
### Integration Points
|
||||
|
||||
#### Internal Communication
|
||||
|
||||
```
|
||||
Frontend (Next.js)
|
||||
↓ fetch /api/v1/*
|
||||
Backend (FastAPI)
|
||||
↓ SQLAlchemy
|
||||
Database (PostgreSQL)
|
||||
↓
|
||||
Redis (Rate Limiting + Cache)
|
||||
```
|
||||
|
||||
#### External Integrations
|
||||
|
||||
| Service | Module | Usage |
|
||||
|---------|--------|-------|
|
||||
| Google Translate | `providers/google.py` | Classic translation |
|
||||
| DeepL | `providers/deepl.py` | Classic translation |
|
||||
| Ollama | `providers/ollama.py` | LLM translation |
|
||||
| OpenAI | `providers/openai.py` | LLM translation |
|
||||
| Webhooks (User) | `webhooks/service.py` | POST to user URL |
|
||||
|
||||
### Development Workflow
|
||||
|
||||
**Démarrage Local:**
|
||||
```bash
|
||||
docker-compose -f docker-compose.dev.yml up -d
|
||||
# Backend: http://localhost:8000
|
||||
# Frontend: http://localhost:3000
|
||||
# API Docs: http://localhost:8000/docs
|
||||
```
|
||||
|
||||
**Migrations:**
|
||||
```bash
|
||||
cd backend
|
||||
alembic revision --autogenerate -m "description"
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
## Architecture Validation Results
|
||||
|
||||
### Coherence Validation ✅
|
||||
|
||||
**Decision Compatibility:**
|
||||
| Stack | Compatibilité |
|
||||
|-------|---------------|
|
||||
| FastAPI + Pydantic v2 | ✅ Natif, parfait |
|
||||
| SQLAlchemy 2.0 + Alembic | ✅ Standard, éprouvé |
|
||||
| PyJWT + passlib[bcrypt] | ✅ Stack auth standard |
|
||||
| Next.js 15 + TanStack Query | ✅ Moderne, best practice |
|
||||
| PostgreSQL + Redis | ✅ Combo classique SaaS |
|
||||
| structlog + JSON logs | ✅ Cohérent avec Admin Dashboard |
|
||||
|
||||
**Pattern Consistency:**
|
||||
- snake_case DB/API ↔ camelCase Frontend (convention par langage) ✅
|
||||
- App Router fichiers minuscules ↔ Colocation components/hooks ✅
|
||||
- Response wrapper {data, meta} ↔ Error format {error, message} ✅
|
||||
|
||||
**Structure Alignment:**
|
||||
- Backend: Clean Architecture modulaire → 5 modules métier ✅
|
||||
- Frontend: Colocation par feature → fichiers proches de leur usage ✅
|
||||
- Mapping FRs → Emplacements documenté ✅
|
||||
|
||||
### Requirements Coverage Validation ✅
|
||||
|
||||
**Functional Requirements Coverage (66 FRs):**
|
||||
|
||||
| Catégorie | FRs | Status |
|
||||
|-----------|-----|--------|
|
||||
| Document Translation | FR1-FR8 | ✅ Couvert |
|
||||
| Format Preservation | FR9-FR16 | ✅ Couvert |
|
||||
| User Management & Auth | FR17-FR22 | ✅ Couvert |
|
||||
| Subscription & Billing | FR23-FR28 | ✅ Couvert |
|
||||
| API & Integration | FR29-FR35 | ✅ Couvert |
|
||||
| Webhooks | FR36-FR38, FR65-FR66 | ✅ Couvert |
|
||||
| Admin Dashboard | FR39-FR45 | ✅ Couvert |
|
||||
| Web UI | FR46-FR49 | ✅ Couvert |
|
||||
| File Management | FR50-FR54 | ✅ Couvert |
|
||||
| Error Handling | FR55-FR57 | ✅ Couvert |
|
||||
| Glossaries & Prompts | FR58-FR61 | ✅ Couvert (MVP) |
|
||||
| URL Ingestion | FR62-FR64 | ✅ Couvert |
|
||||
|
||||
**Non-Functional Requirements Coverage (21 NFRs):**
|
||||
|
||||
| Catégorie | NFRs | Status |
|
||||
|-----------|------|--------|
|
||||
| Performance | NFR1-NFR5 | ✅ Async + TanStack Query |
|
||||
| Security | NFR6-NFR11 | ✅ JWT + API Keys + HTTPS |
|
||||
| Reliability | NFR12-NFR14 | ✅ Error handler + fallback |
|
||||
| Data Retention | NFR15-NFR17 | ✅ TTL 60min + zero retention |
|
||||
| API Quality | NFR18-NFR21 | ✅ OpenAPI + JSON errors + versioning |
|
||||
|
||||
### Implementation Readiness Validation ✅
|
||||
|
||||
**Decision Completeness:**
|
||||
- [x] Technologies avec versions documentées
|
||||
- [x] Patterns de nommage complets
|
||||
- [x] Formats API (succès + erreur)
|
||||
- [x] Règles critiques (App Router, colocation)
|
||||
|
||||
**Structure Completeness:**
|
||||
- [x] Arbre complet backend + frontend
|
||||
- [x] Fichiers de configuration définis
|
||||
- [x] Migrations Alembic nommées
|
||||
- [x] Tests organisés
|
||||
|
||||
**Pattern Completeness:**
|
||||
- [x] Naming conventions
|
||||
- [x] API response formats
|
||||
- [x] Error codes
|
||||
- [x] Rate limiting logic
|
||||
|
||||
### Gap Analysis
|
||||
|
||||
**Critical Gaps:** Aucun ✅
|
||||
|
||||
**Important Gaps:** Aucun ✅
|
||||
|
||||
**Nice-to-Have (Post-MVP):**
|
||||
- CI/CD pipeline (peut être défini lors implémentation)
|
||||
- PDF support (PRD: future feature)
|
||||
- Prometheus/Grafana (health checks suffisent)
|
||||
|
||||
### Architecture Completeness Checklist
|
||||
|
||||
**✅ Requirements Analysis**
|
||||
- [x] Project context analysé
|
||||
- [x] Scale et complexité évalués
|
||||
- [x] Contraintes techniques identifiées
|
||||
- [x] Cross-cutting concerns mappés
|
||||
|
||||
**✅ Architectural Decisions**
|
||||
- [x] Décisions critiques documentées avec versions
|
||||
- [x] Stack technologique complète
|
||||
- [x] Patterns d'intégration définis
|
||||
- [x] Considérations performance adressées
|
||||
|
||||
**✅ Implementation Patterns**
|
||||
- [x] Naming conventions établies
|
||||
- [x] Structure patterns définis
|
||||
- [x] Communication patterns spécifiés
|
||||
- [x] Process patterns documentés
|
||||
|
||||
**✅ Project Structure**
|
||||
- [x] Directory structure complète
|
||||
- [x] Component boundaries établies
|
||||
- [x] Integration points mappés
|
||||
- [x] Requirements → Structure mapping
|
||||
|
||||
### Architecture Readiness Assessment
|
||||
|
||||
**Overall Status:** 🟢 **READY FOR IMPLEMENTATION**
|
||||
|
||||
**Confidence Level:** HIGH
|
||||
|
||||
**Key Strengths:**
|
||||
- Stack technologique cohérente et moderne
|
||||
- Clean Architecture modulaire (maintenabilité)
|
||||
- Colocation frontend (DX excellent pour solo dev)
|
||||
- 100% FRs/NFRs couverts
|
||||
- Patterns anti-conflit documentés
|
||||
|
||||
**Areas for Future Enhancement:**
|
||||
- CI/CD pipeline automation
|
||||
- Advanced monitoring (Prometheus/Grafana)
|
||||
- PDF format support
|
||||
- Team collaboration features
|
||||
|
||||
### Implementation Handoff
|
||||
|
||||
**AI Agent Guidelines:**
|
||||
|
||||
1. ✅ Suivre toutes les décisions architecturales exactement
|
||||
2. ✅ Utiliser les patterns d'implémentation de manière cohérente
|
||||
3. ✅ Respecter la structure projet et les boundaries
|
||||
4. ✅ Se référer à ce document pour toute question architecturale
|
||||
|
||||
**⚠️ Règles Critiques à Respecter:**
|
||||
```
|
||||
🚨 NEXT.JS: page.tsx, layout.tsx TOUJOURS minuscules
|
||||
🚨 COLOCATION: Components/hooks/types dans le dossier de leur page
|
||||
🚨 API JSON: snake_case (pas camelCase)
|
||||
🚨 RESPONSE: {data, meta} succès / {error, message} erreur
|
||||
```
|
||||
|
||||
**First Implementation Priority:**
|
||||
1. Setup Alembic migrations (001_initial_users.py)
|
||||
2. Core: Auth module (PyJWT + passlib)
|
||||
3. Core: Translation module (providers abstraction)
|
||||
4. API: REST endpoints /api/v1/*
|
||||
5. Frontend: TanStack Query + colocation structure
|
||||
|
||||
---
|
||||
|
||||
*Document généré via workflow BMAD create-architecture — 2026-02-18*
|
||||
1284
_bmad-output/planning-artifacts/epics.md
Normal file
1284
_bmad-output/planning-artifacts/epics.md
Normal file
File diff suppressed because it is too large
Load Diff
74
_bmad-output/planning-artifacts/prd-validation-report.md
Normal file
74
_bmad-output/planning-artifacts/prd-validation-report.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
validationTarget: '_bmad-output/planning-artifacts/prd.md'
|
||||
validationDate: '2026-02-18'
|
||||
inputDocuments:
|
||||
- product-brief-office_translator-2026-02-18.md
|
||||
validationStepsCompleted:
|
||||
- step-v-01-discovery
|
||||
- step-v-02-format-detection
|
||||
- step-v-03-density-validation
|
||||
- step-v-04-brief-coverage-validation
|
||||
- step-v-05-measurability-validation
|
||||
- step-v-06-traceability-validation
|
||||
- step-v-07-implementation-leakage-validation
|
||||
- step-v-08-domain-compliance-validation
|
||||
- step-v-09-project-type-validation
|
||||
- step-v-10-smart-validation
|
||||
- step-v-11-holistic-quality-validation
|
||||
- step-v-12-completeness-validation
|
||||
validationStatus: COMPLETE
|
||||
holisticQualityRating: '5/5'
|
||||
overallStatus: PASS
|
||||
---
|
||||
|
||||
# PRD Validation Report
|
||||
|
||||
**PRD Being Validated:** _bmad-output/planning-artifacts/prd.md
|
||||
**Validation Date:** 2026-02-18
|
||||
|
||||
## Input Documents
|
||||
|
||||
- PRD: prd.md
|
||||
- Product Brief: product-brief-office_translator-2026-02-18.md
|
||||
|
||||
## Validation Summary
|
||||
|
||||
### Quick Results
|
||||
|
||||
| Check | Status |
|
||||
|-------|--------|
|
||||
| Format Detection | ✓ BMAD Standard (6/6 core sections) |
|
||||
| Information Density | ✓ Pass (0 violations) |
|
||||
| Product Brief Coverage | ✓ Pass (all key content covered) |
|
||||
| Measurability | ✓ Pass (0 violations) |
|
||||
| Traceability | ✓ Pass (0 orphans) |
|
||||
| Implementation Leakage | ✓ Pass (0 violations) |
|
||||
| Domain Compliance | ✓ Pass (appropriate for B2B SaaS) |
|
||||
| Project-Type Compliance | ✓ Pass (100%) |
|
||||
| SMART Requirements | ✓ Pass (100% at 5/5) |
|
||||
| Holistic Quality | ✓ Excellent (5/5) |
|
||||
| Completeness | ✓ Pass (100%) |
|
||||
|
||||
### Critical Issues: None
|
||||
|
||||
### Warnings: None
|
||||
|
||||
### Strengths
|
||||
- Vision claire avec insight unique (élimination du travail post-traduction)
|
||||
- 66 FRs précises, mesurables et traçables
|
||||
- 21 NFRs avec critères spécifiques
|
||||
- 4 User Journeys couvrant tous les personas
|
||||
- Structure BMAD Standard complète
|
||||
- Zero anti-patterns ou fuite d'implémentation
|
||||
- Documentation de domaine appropriée (RGPD, confidentialité)
|
||||
|
||||
### Holistic Quality: 5/5 - Excellent
|
||||
|
||||
### Top 3 Improvements
|
||||
1. Ajouter un glossaire de termes techniques
|
||||
2. Inclure un diagramme d'architecture visuel
|
||||
3. Documenter les dépendances entre FRs
|
||||
|
||||
### Recommendation
|
||||
PRD is in excellent shape. The document is ready for downstream work (Architecture, UX, Epics). Consider the minor improvements above to make it even better.
|
||||
|
||||
559
_bmad-output/planning-artifacts/prd.md
Normal file
559
_bmad-output/planning-artifacts/prd.md
Normal file
@@ -0,0 +1,559 @@
|
||||
---
|
||||
stepsCompleted: [step-01-init, step-02-discovery, step-02b-vision, step-02c-executive-summary, step-03-success, step-04-journeys, step-05-domain, step-06-innovation, step-07-project-type, step-08-scoping, step-09-functional, step-10-nonfunctional, step-11-polish, step-12-complete]
|
||||
inputDocuments:
|
||||
- product-brief-office_translator-2026-02-18.md
|
||||
workflowType: 'prd'
|
||||
documentCounts:
|
||||
briefs: 1
|
||||
research: 0
|
||||
projectDocs: 0
|
||||
classification:
|
||||
projectType: 'Application web SaaS + API REST'
|
||||
domain: 'Traduction de documents / Productivité B2B'
|
||||
complexity: 'Moyenne-Haute'
|
||||
projectContext: 'brownfield'
|
||||
date: 2026-02-18
|
||||
---
|
||||
|
||||
# Product Requirements Document - office_translator
|
||||
|
||||
**Author:** Sepehr
|
||||
**Date:** 2026-02-18
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Office Translator est une plateforme SaaS de traduction de documents Office (Excel, Word, PowerPoint) qui résout un problème critique pour les entreprises : le **temps perdu à remettre en page un document mal traduit** coûte plus cher que la traduction elle-même.
|
||||
|
||||
La vision est simple — l'utilisateur dépose un document, le récupère traduit et **visuellement identique** à l'original (couleurs, cellules fusionnées, graphiques, mises en page), sans aucune retouche nécessaire.
|
||||
|
||||
**Cible** : Professionnels et entreprises ayant besoin de traduire des documents Office complexes avec une qualité "prête à l'emploi".
|
||||
|
||||
### What Makes This Special
|
||||
|
||||
- **Sanitisation et reconstruction de document supérieure** : Notre traitement des fichiers Office dépasse les solutions existantes sur la préservation du format.
|
||||
- **Fiabilité sur l'expérimentation** : Utilisation de moteurs éprouvés (LLMs stables : Ollama, OpenAI, compatibles) plutôt que des IA génératives instables.
|
||||
- **Administration SaaS robuste** : Monitoring, abonnements, rate limiting — pensé pour un déploiement production et une monétisation sereine.
|
||||
|
||||
**Insight unique** : La valeur n'est pas dans la traduction elle-même, mais dans l'élimination du travail post-traduction.
|
||||
|
||||
## Project Classification
|
||||
|
||||
| Élément | Valeur |
|
||||
|---------|--------|
|
||||
| **Type** | Application web SaaS + API REST |
|
||||
| **Domaine** | Traduction de documents / Productivité B2B |
|
||||
| **Complexité** | Moyenne-Haute |
|
||||
| **Contexte** | Brownfield (refonte de l'existant) |
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### User Success
|
||||
|
||||
**Rapidité (avec distinction par mode)** :
|
||||
- Mode Classique (Google/DeepL) : < 15 secondes pour un document standard (ex: Word 10 pages) — impression d'instantanéité
|
||||
- Mode LLM (Ollama/OpenAI) : 1 à 3 minutes acceptables si barre de progression claire
|
||||
- **Critère clé** : Feedback visuel (progression) immédiat dans tous les cas
|
||||
|
||||
**Qualité "prête à l'emploi"** :
|
||||
- Format Fidelity : Le fichier traduit s'ouvre sans erreur dans Office
|
||||
- Zéro casse visuelle : 0% de tableaux explosés, images déplacées, mises en page brisées
|
||||
- Taux de retouche < 10% : l'utilisateur corrige une tournure, jamais ne reconstruit le document
|
||||
|
||||
### Business Success (MVP)
|
||||
|
||||
**Objectif : Capacité à Facturer (Billability)** :
|
||||
- Le système de tracking (Admin) remonte 100% des usages réels
|
||||
- Le système de quotas (Rate Limiting) bloque effectivement les abus
|
||||
- **Définition du succès** : Si déployé demain, possibilité d'onboarder un client payant sans risque de consommation illimitée gratuite
|
||||
|
||||
### Technical Success
|
||||
|
||||
- **Fiabilité** : Gestion d'erreurs "graceful" — fichiers corrompus/illisibles → erreur 400 claire (JSON), jamais de crash serveur (500)
|
||||
- **Hygiène** : 100% des fichiers temporaires supprimés après TTL (confidentialité + espace disque)
|
||||
- **Performance** : 5 conversions simultanées sans ralentissement perceptible de l'interface Admin
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
| Critère | Cible |
|
||||
|---------|-------|
|
||||
| Temps de traduction (mode classique) | < 15 sec (doc 10 pages) |
|
||||
| Temps de traduction (mode LLM) | 1-3 min avec progression |
|
||||
| Taux de retouche utilisateur | < 10% |
|
||||
| Fichiers ouvrables sans erreur | 100% |
|
||||
| Caisse visuelle (format) | 0% |
|
||||
| Couverture tracking usage | 100% |
|
||||
| Nettoyage fichiers temporaires | 100% |
|
||||
| Conversions simultanées supportées | 5 |
|
||||
|
||||
## Product Scope
|
||||
|
||||
### MVP - Minimum Viable Product
|
||||
|
||||
- Refonte backend : code épuré, suppression code mort
|
||||
- Traduction via LLMs (Ollama, OpenAI, compatibles) + Google/DeepL si API pas chère
|
||||
- Préservation parfaite du format (Excel, Word, PowerPoint)
|
||||
- Système de tracking usage (Admin)
|
||||
- Rate limiting par utilisateur/abonnement
|
||||
- Gestion d'erreurs robuste
|
||||
- Nettoyage automatique des fichiers temporaires
|
||||
|
||||
### Growth Features (Post-MVP)
|
||||
|
||||
- Intégration API Google Traduction officielle (si coût acceptable)
|
||||
- Dashboard analytics avancé
|
||||
- Historique de traductions pour utilisateurs
|
||||
- Webhooks / notifications
|
||||
- Support de formats supplémentaires (PDF ?)
|
||||
|
||||
### Vision (Future)
|
||||
|
||||
- Mode "Team" avec collaboration
|
||||
- Intégrations (Zapier, Make, etc.)
|
||||
- API publique documentée pour développeurs tiers
|
||||
- Marketplace de templates/glossaires
|
||||
|
||||
## User Journeys
|
||||
|
||||
### Journey 1 : Marie, Utilisatrice Web Gratuite
|
||||
|
||||
**Situation** : Marie est consultante marketing freelance. Elle reçoit un rapport PowerPoint en anglais d'un client et doit le présenter en français à une réunion dans 2 heures.
|
||||
|
||||
**Parcours** :
|
||||
1. Marie découvre Office Translator via une recherche ou bouche-à-oreille
|
||||
2. Elle arrive sur la page d'accueil, comprend immédiatement le propos (traduction de documents, format préservé)
|
||||
3. Elle glisse-dépose son fichier PPT (15 slides)
|
||||
4. Elle sélectionne "Anglais → Français" et choisit le mode "Classique" (gratuit, rapide)
|
||||
5. Une barre de progression s'affiche immédiatement : "Traitement en cours... 3/15 slides"
|
||||
6. Après 12 secondes, le fichier est prêt → téléchargement automatique
|
||||
7. Elle ouvre le fichier : le design est intact, les graphiques sont en place
|
||||
8. Elle corrige 2-3 tournures de phrases, sauvegarde et envoie à la réunion
|
||||
|
||||
**Résultat** : Mission accomplie en moins de 5 minutes. Elle bookmark le site.
|
||||
|
||||
**Exigences révélées** : Landing page claire, upload drag & drop, feedback visuel temps réel, téléchargement fluide, qualité de format.
|
||||
|
||||
### Journey 2 : Thomas, Utilisateur API Pro
|
||||
|
||||
**Situation** : Thomas est lead dev dans un cabinet d'audit. Son équipe traite 200 rapports financiers Excel par mois pour des clients internationaux. Il automatise avec n8n.
|
||||
|
||||
**Parcours** :
|
||||
1. Thomas s'abonne au plan Pro (gestion manuelle par Admin pour le MVP)
|
||||
2. Il accède à son Dashboard → génère une **Clé API stable**
|
||||
3. Il lit la documentation API : endpoints, auth, rate limits, codes d'erreur JSON
|
||||
4. Il configure son workflow n8n avec la clé API
|
||||
5. Premier test : fichier Excel complexe envoyé → réponse structurée (fichier + métadonnées)
|
||||
6. Il teste un cas d'erreur : quota dépassé → API renvoie `{"error": "quota_exceeded", "message": "Limite mensuelle atteinte"}`
|
||||
7. Il active les **fonctionnalités Pro** : Glossaires personnalisés + Prompts système pour la terminologie financière
|
||||
8. Déploiement production → 200 fichiers/mois traités, erreurs gérées automatiquement par ses scripts
|
||||
|
||||
**Résultat** : Gain de 15h/mois. Sa raison de payer : personnalisation terminologique + volume.
|
||||
|
||||
**Exigences révélées** : Génération Clés API dans Dashboard, erreurs JSON structurées, documentation, Glossaires/Prompts système (Pro).
|
||||
|
||||
### Journey 3 : L'Admin (Dashboard)
|
||||
|
||||
**Situation** : C'est vous, lundi matin. Vous vérifiez le système et gérez les premiers clients.
|
||||
|
||||
**Parcours** :
|
||||
1. Connexion au Dashboard Admin (auth sécurisée)
|
||||
2. Vue d'ensemble : santé système, espace disque, mémoire, statut providers
|
||||
3. **Gestion des utilisateurs** : vous voyez une nouvelle demande de Thomas
|
||||
4. Vous passez Thomas de "Free" à "Pro" manuellement (dropdown → "Pro")
|
||||
5. Sa Clé API est automatiquement générée/activée dans son Dashboard utilisateur
|
||||
6. Vous vérifiez les stats : 847 traductions ce weekend, 3 erreurs gérées proprement (400)
|
||||
7. Vérification du rate limiting : utilisateur X bloqué après quota gratuit
|
||||
8. Purge des fichiers temporaires orphelins → système propre
|
||||
|
||||
**Résultat** : Client Pro onboardé manuellement, système stable, prêt pour la facturation.
|
||||
|
||||
**Exigences révélées** : Dashboard métriques, **changement de tier manuel** (Free→Pro), **génération/révocation clés API**, statut providers, logs, purge fichiers.
|
||||
|
||||
### Journey 4 : Cas d'Erreur - Fichier Non Supporté
|
||||
|
||||
**Situation** : Un utilisateur essaie de traduire un PDF scanné.
|
||||
|
||||
**Parcours** :
|
||||
1. Upload du fichier PDF
|
||||
2. Le système détecte le format non supporté
|
||||
3. API renvoie : `{"error": "invalid_format", "message": "Format PDF non supporté. Formats acceptés : .xlsx, .docx, .pptx"}`
|
||||
4. L'utilisateur comprend et convertit son fichier
|
||||
5. Deuxième tentative : succès
|
||||
|
||||
**Résultat** : Pas de frustration, message explicite, pas de crash serveur.
|
||||
|
||||
**Exigences révélées** : Validation format, erreurs JSON utilisateur-friendly, gestion graceful.
|
||||
|
||||
### Journey Requirements Summary
|
||||
|
||||
| Parcours | Capacités Révélées |
|
||||
|----------|-------------------|
|
||||
| Utilisateur Web Gratuit | Landing page, upload drag & drop, progression temps réel, téléchargement |
|
||||
| Utilisateur API Pro | **Génération Clés API**, documentation, erreurs JSON structurées, **Glossaires/Prompts (Pro)** |
|
||||
| Admin Dashboard | Métriques système, **changement de tier manuel**, **gestion clés API**, statut providers, logs, purge |
|
||||
| Gestion d'erreurs | Validation format, erreurs JSON claires, graceful degradation |
|
||||
|
||||
## Domain-Specific Requirements
|
||||
|
||||
### Confidentialité des données (Data Confidentiality)
|
||||
|
||||
- **Politique "Zéro Rétention"** : Système "Passe-plat" (Pass-through)
|
||||
- **Stockage** : Strictement temporaire (/tmp), suppression automatique (Hard Delete) après TTL de 60 minutes ou immédiatement après téléchargement réussi
|
||||
- **Logs** : Aucun contenu de document loggué. Seules métadonnées conservées (nom, taille, hash, timestamp)
|
||||
|
||||
### RGPD / Conformité (GDPR)
|
||||
|
||||
- **Cible** : Clients européens visés
|
||||
- **Stratégie** : Conformité par minimisation des données — pas de stockage durable = "Droit à l'oubli" respecté par défaut
|
||||
- **Hébergement** : Préférence serveur UE pour le MVP
|
||||
|
||||
### Propriété Intellectuelle (IP)
|
||||
|
||||
- **Clause** : L'utilisateur reste seul propriétaire des documents
|
||||
- **"No Training Policy"** : Garantie que les documents ne sont jamais utilisés pour entraîner les modèles (différenciateur clé B2B)
|
||||
|
||||
### Sécurité API (API Security)
|
||||
|
||||
| Vecteur | Mécanisme |
|
||||
|---------|-----------|
|
||||
| Web/Admin | JWT (Access + Refresh Tokens) |
|
||||
| API Automation | Clés API statiques générées par Admin |
|
||||
| Contrôle | Révocation immédiate via Dashboard (pas de rotation auto MVP) |
|
||||
|
||||
### Audit / Traçabilité
|
||||
|
||||
- **Logs structurés** : Qui, Quand, Quoi, Volume, Status Code
|
||||
- **Usage** : Debugging + facturation/quota (pages traduites)
|
||||
- **Scope** : Pas d'audit légal complexe pour le MVP
|
||||
|
||||
## SaaS B2B + API Backend - Exigences Spécifiques
|
||||
|
||||
### Architecture Multi-Tenant
|
||||
|
||||
| Aspect | Décision |
|
||||
|--------|----------|
|
||||
| Isolation | Par utilisateur (quotas, clés API séparées) |
|
||||
| Stockage | Local éphémère (/tmp) - pas de S3 pour le MVP |
|
||||
| Données persistantes | Utilisateurs, clés API, logs métadonnées uniquement |
|
||||
|
||||
### Modèle de Permissions (RBAC)
|
||||
|
||||
| Rôle | Accès |
|
||||
|------|-------|
|
||||
| **Free** | Traduction web, mode classique uniquement, quota limité |
|
||||
| **Pro** | Traduction web + API, tous modes (LLM inclus), glossaires/prompts, quota élevé |
|
||||
| **Admin** | Dashboard complet, gestion utilisateurs, révocation clés, métriques système |
|
||||
|
||||
### Tiers d'Abonnement
|
||||
|
||||
| Tier | Quota | Providers | Fonctionnalités |
|
||||
|------|-------|-----------|-----------------|
|
||||
| Free | 5 fichiers/jour | Google/DeepL | Traduction web uniquement |
|
||||
| Pro | Illimité (fair use) | Tous (LLM inclus) | API, Glossaires, Prompts système, Webhooks |
|
||||
|
||||
### Spécifications API
|
||||
|
||||
**Versioning :**
|
||||
- Tous les endpoints préfixés par `/api/v1/`
|
||||
- Obligatoire pour préserver les intégrations clients
|
||||
|
||||
**Endpoints principaux :**
|
||||
| Endpoint | Méthode | Description |
|
||||
|----------|---------|-------------|
|
||||
| `/api/v1/translate` | POST | Traduire un document |
|
||||
| `/api/v1/languages` | GET | Langues supportées |
|
||||
| `/api/v1/health` | GET | Santé du service |
|
||||
| `/api/v1/download/{id}` | GET | Télécharger fichier traduit |
|
||||
|
||||
**Authentification :**
|
||||
| Contexte | Méthode |
|
||||
|----------|---------|
|
||||
| Web/Admin | JWT (Access + Refresh Tokens) |
|
||||
| API Automation | API Key statique (header `X-API-Key`) |
|
||||
|
||||
**Gestion d'erreurs :**
|
||||
- Format JSON structuré : `{"error": "code", "message": "description"}`
|
||||
- Codes HTTP appropriés (400 client, 500 server - à éviter)
|
||||
|
||||
**Documentation :**
|
||||
- OpenAPI (Swagger/Redoc) interactif
|
||||
- Pas de SDK client pour le MVP
|
||||
|
||||
### Intégrations & Webhooks
|
||||
|
||||
| Intégration | Statut MVP |
|
||||
|-------------|------------|
|
||||
| Stockage S3 | Non (local éphémère) |
|
||||
| Email transactionnel | Non (gestion manuelle Admin) |
|
||||
| **Webhooks** | **Oui** - Fire & Forget (POST URL client après traduction) |
|
||||
|
||||
### Exigences de Conformité
|
||||
|
||||
| Exigence | Implémentation |
|
||||
|----------|----------------|
|
||||
| RGPD | Minimisation données (zero retention) |
|
||||
| Confidentialité | TTL 60 min, hard delete automatique |
|
||||
| Hébergement | Préférence UE |
|
||||
| "No Training Policy" | Clause contractuelle |
|
||||
|
||||
## Project Scoping & Phased Development
|
||||
|
||||
### MVP Strategy & Philosophy
|
||||
|
||||
**Approche MVP** : Revenue-Ready Hybride
|
||||
- Module paiement existant à refactorer (Clean Architecture)
|
||||
- Gestion manuelle Admin en backup (sécurité support client)
|
||||
- Objectif : déployer avec capacité de facturer immédiatement
|
||||
|
||||
**Parcours prioritaire** : Thomas (API Pro) — API first, revenus first
|
||||
|
||||
**Ressources** : Solo Developer → Architecture monolithique modulaire
|
||||
|
||||
### MVP Feature Set (Phase 1)
|
||||
|
||||
**Parcours utilisateurs supportés :**
|
||||
| Parcours | Priorité MVP |
|
||||
|----------|--------------|
|
||||
| Thomas (API Pro) | **Critique** — Priorité absolue |
|
||||
| Admin Dashboard | **Critique** — Gestion clients + monitoring |
|
||||
| Marie (Web Gratuit) | Important — Acquisition utilisateur |
|
||||
| Gestion d'erreurs | **Critique** — Expérience API |
|
||||
|
||||
**Must-Have Capabilities :**
|
||||
|
||||
| Capacité | Priorité | Notes |
|
||||
|----------|----------|-------|
|
||||
| Traduction Excel/Word/PPT | **Critique** | Risque technique n°1 |
|
||||
| Préservation format | **Critique** | Cœur de valeur |
|
||||
| API /v1/ + documentation OpenAPI | **Critique** | Parcours Thomas |
|
||||
| Clés API (génération/révocation) | **Critique** | Parcours Thomas |
|
||||
| Erreurs JSON structurées | **Critique** | Parcours Thomas |
|
||||
| Webhooks (Fire & Forget) | **Critique** | Automation |
|
||||
| Dashboard Admin | **Critique** | Monitoring + gestion |
|
||||
| Changement tier manuel (Free→Pro) | **Critique** | Backup paiement |
|
||||
| Module paiement refactoré | Important | Revenue-ready |
|
||||
| Rate limiting | **Critique** | Protection abus |
|
||||
| Nettoyage fichiers (TTL 60min) | **Critique** | Confidentialité |
|
||||
| Auth JWT (Admin) | **Critique** | Sécurité |
|
||||
| Upload Web drag & drop | Important | Parcours Marie |
|
||||
| Barre progression | Important | UX |
|
||||
|
||||
**Peut attendre Post-MVP :**
|
||||
- Historique traductions utilisateur
|
||||
- Dashboard analytics avancé
|
||||
- Intégrations Zapier/Make
|
||||
- SDK client
|
||||
|
||||
### Post-MVP Features
|
||||
|
||||
**Phase 2 (Growth) :**
|
||||
- Glossaires personnalisés (Pro)
|
||||
- Prompts système personnalisables
|
||||
- Historique de traductions
|
||||
- Dashboard analytics avancé
|
||||
- Support PDF (si demandé)
|
||||
|
||||
**Phase 3 (Expansion) :**
|
||||
- Mode Team / collaboration
|
||||
- Intégrations Zapier, Make
|
||||
- API publique pour développeurs tiers
|
||||
- SDK client (Python, JS)
|
||||
- Marketplace templates/glossaires
|
||||
|
||||
### Risk Mitigation Strategy
|
||||
|
||||
| Risque | Type | Mitigation |
|
||||
|--------|------|------------|
|
||||
| **Préservation format Office** | Technique | Tests automatisés sur fichiers complexes, validation visuelle, corpus de test |
|
||||
| Intégration multi-providers LLM | Technique | Abstraction provider, fallback entre providers |
|
||||
| Bug paiement | Business | Gestion manuelle Admin en backup |
|
||||
| Solo developer | Ressource | Monolithe modulaire, scope strict, dette technique zero |
|
||||
| Acquisition utilisateurs | Marché | Parcours Marie fonctionnel, bouche-à-oreille |
|
||||
|
||||
### Architecture Decision
|
||||
|
||||
**Monolithe Modulaire** (pas de micro-services) :
|
||||
- `modules/translation/` — cœur métier
|
||||
- `modules/auth/` — JWT + API Keys
|
||||
- `modules/payment/` — paiement refactoré
|
||||
- `modules/admin/` — dashboard
|
||||
- `modules/webhooks/` — notifications
|
||||
|
||||
## Functional Requirements
|
||||
|
||||
### Document Translation
|
||||
|
||||
- FR1: Users can upload Excel files (.xlsx) for translation
|
||||
- FR2: Users can upload Word files (.docx) for translation
|
||||
- FR3: Users can upload PowerPoint files (.pptx) for translation
|
||||
- FR4: Users can select source and target languages for translation
|
||||
- FR5: Users can choose translation mode (Classic or LLM) based on their subscription tier
|
||||
- FR6: System can translate documents using Google/DeepL providers (Classic mode)
|
||||
- FR7: System can translate documents using LLM providers (Ollama, OpenAI, OpenAI-compatible)
|
||||
- FR8: System can process multiple translation requests concurrently
|
||||
|
||||
### Format Preservation
|
||||
|
||||
- FR9: System preserves document layout after translation (colors, fonts, spacing)
|
||||
- FR10: System preserves merged cells in Excel files
|
||||
- FR11: System preserves tables in Word and PowerPoint files
|
||||
- FR12: System preserves images and their positions in all document types
|
||||
- FR13: System preserves charts and their data links in Excel files
|
||||
- FR14: System preserves formulas in Excel files (translating only text content)
|
||||
- FR15: System preserves slide layouts and animations in PowerPoint files
|
||||
- FR16: Users can open translated files in Microsoft Office without errors
|
||||
|
||||
### User Management & Authentication
|
||||
|
||||
- FR17: Users can create an account with email and password
|
||||
- FR18: Users can log in to the web application via JWT authentication
|
||||
- FR19: Users can log out of the web application
|
||||
- FR20: System assigns users to subscription tiers (Free or Pro)
|
||||
- FR21: Admin can change user tier from Free to Pro manually
|
||||
- FR22: Admin can change user tier from Pro to Free manually
|
||||
|
||||
### Subscription & Billing
|
||||
|
||||
- FR23: System enforces daily file quotas based on user tier
|
||||
- FR24: Free users are limited to 5 files per day
|
||||
- FR25: Pro users have unlimited translations (fair use policy)
|
||||
- FR26: Pro users can access LLM translation modes
|
||||
- FR27: System tracks translation usage per user for billing purposes
|
||||
- FR28: Payment module updates user tier upon successful payment
|
||||
|
||||
### API & Integration
|
||||
|
||||
- FR29: Pro users can generate API keys from their dashboard
|
||||
- FR30: Pro users can revoke their own API keys
|
||||
- FR31: Admin can revoke any user's API key
|
||||
- FR32: System authenticates API requests via X-API-Key header
|
||||
- FR33: System provides REST API endpoints under /api/v1/ prefix
|
||||
- FR34: System returns errors in structured JSON format with error code and message
|
||||
- FR35: System provides interactive API documentation (OpenAPI/Swagger)
|
||||
|
||||
### Webhooks
|
||||
|
||||
- FR36: Users can specify webhook URL per translation request (passed as parameter)
|
||||
- FR37: System sends POST request to webhook URL when translation completes
|
||||
- FR38: System includes translation metadata in webhook payload (file ID, status, timestamp)
|
||||
- FR65: Webhook URL is passed as parameter in the API request body
|
||||
- FR66: System sends webhook notification only if URL is provided in request
|
||||
|
||||
### Admin Dashboard
|
||||
|
||||
- FR39: Admin can log in to admin dashboard with secure authentication
|
||||
- FR40: Admin can view system health metrics (disk space, memory usage)
|
||||
- FR41: Admin can view provider status (Google, DeepL, Ollama, OpenAI connectivity)
|
||||
- FR42: Admin can view translation statistics (count, errors, usage)
|
||||
- FR43: Admin can view rate limiting status per user
|
||||
- FR44: Admin can trigger manual cleanup of orphaned temporary files
|
||||
- FR45: Admin can view error logs with structured information
|
||||
|
||||
### Web User Interface
|
||||
|
||||
- FR46: Users can upload files via drag-and-drop interface
|
||||
- FR47: Users see real-time progress indicator during translation
|
||||
- FR48: Users can download translated files after completion
|
||||
- FR49: Users receive clear error messages for unsupported file formats
|
||||
|
||||
### File Management
|
||||
|
||||
- FR50: System validates file format before processing (xlsx, docx, pptx only)
|
||||
- FR51: System stores uploaded files in temporary location
|
||||
- FR52: System automatically deletes files after TTL (60 minutes)
|
||||
- FR53: System deletes files immediately after successful download
|
||||
- FR54: System logs file metadata (name, size, hash, timestamp) without content
|
||||
|
||||
### Error Handling
|
||||
|
||||
- FR55: System returns HTTP 400 errors for client-side issues (invalid format, quota exceeded)
|
||||
- FR56: System never returns HTTP 500 errors (graceful degradation required)
|
||||
- FR57: System provides actionable error messages in user's language
|
||||
|
||||
### Glossaries & Custom Prompts (Pro Feature)
|
||||
|
||||
- FR58: Pro users can include a custom glossary in translation requests
|
||||
- FR59: Pro users can include custom system prompt/instructions in translation requests
|
||||
- FR60: System applies glossary terms during LLM translation
|
||||
- FR61: System applies custom prompts to guide LLM translation context
|
||||
|
||||
### URL Ingestion (Automation)
|
||||
|
||||
- FR62: API can accept a file URL as input (in addition to binary upload)
|
||||
- FR63: System downloads files from public URLs (S3, Drive, etc.) before processing
|
||||
- FR64: System validates downloaded files against supported formats
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
### Performance
|
||||
|
||||
| ID | Exigence | Critère |
|
||||
|----|----------|---------|
|
||||
| NFR1 | Temps de réponse mode classique | < 15 secondes pour document 10 pages |
|
||||
| NFR2 | Temps de réponse mode LLM | 1-3 minutes maximum avec progression visible |
|
||||
| NFR3 | Feedback utilisateur | Progression affichée en temps réel (< 500ms latence) |
|
||||
| NFR4 | Concurrence | 5 conversions simultanées sans dégradation perceptible |
|
||||
| NFR5 | Interface Admin | Réponse < 2 secondes même pendant conversions |
|
||||
|
||||
### Security
|
||||
|
||||
| ID | Exigence | Critère |
|
||||
|----|----------|---------|
|
||||
| NFR6 | Authentification Web | JWT avec Access Token (15min) + Refresh Token (7 jours) |
|
||||
| NFR7 | Authentification API | Clés API (256-bit minimum) via header X-API-Key |
|
||||
| NFR8 | Chiffrement transit | HTTPS obligatoire (TLS 1.2+) |
|
||||
| NFR9 | Chiffrement repos | Non requis (pas de stockage persistant de documents) |
|
||||
| NFR10 | Secrets | Variables d'environnement, jamais dans le code |
|
||||
| NFR11 | Données sensibles | Aucun contenu de document dans les logs |
|
||||
|
||||
### Reliability
|
||||
|
||||
| ID | Exigence | Critère |
|
||||
|----|----------|---------|
|
||||
| NFR12 | Gestion d'erreurs | 0% d'erreurs HTTP 500 - toujours retour 4xx avec message JSON |
|
||||
| NFR13 | Disponibilité providers | Fallback automatique entre providers si l'un échoue |
|
||||
| NFR14 | Récupération fichiers | Fichiers temporaires nettoyés même après crash (TTL 60min) |
|
||||
|
||||
### Data Retention & Privacy
|
||||
|
||||
| ID | Exigence | Critère |
|
||||
|----|----------|---------|
|
||||
| NFR15 | Rétention fichiers | 60 minutes maximum, suppression après téléchargement |
|
||||
| NFR16 | Logs | Métadonnées uniquement (nom, taille, hash, timestamp) |
|
||||
| NFR17 | RGPD | Droit à l'oubli respecté par design (zero retention) |
|
||||
|
||||
### API Quality
|
||||
|
||||
| ID | Exigence | Critère |
|
||||
|----|----------|---------|
|
||||
| NFR18 | Documentation | OpenAPI 3.0 interactif (Swagger UI ou Redoc) |
|
||||
| NFR19 | Erreurs API | Format JSON structuré : `{error, message, details?}` |
|
||||
| NFR20 | Rate limiting | Par utilisateur, réponse 429 avec `Retry-After` header |
|
||||
| NFR21 | Versioning | Préfixe /api/v1/ obligatoire |
|
||||
|
||||
---
|
||||
|
||||
## Document Summary
|
||||
|
||||
**Office Translator PRD — Version MVP**
|
||||
|
||||
| Métrique | Valeur |
|
||||
|----------|--------|
|
||||
| Exigences Fonctionnelles | 66 FRs |
|
||||
| Exigences Non-Fonctionnelles | 21 NFRs |
|
||||
| Parcours Utilisateurs | 4 |
|
||||
| Tiers d'abonnement | 2 (Free, Pro) |
|
||||
| Formats supportés | 3 (xlsx, docx, pptx) |
|
||||
|
||||
**Traceabilité :**
|
||||
- Vision → Success Criteria → User Journeys → Functional Requirements → NFRs
|
||||
- Toutes les FRs sont traçables vers un besoin utilisateur ou business
|
||||
- Les NFRs définissent les critères de qualité mesurables
|
||||
|
||||
**Prochaines étapes BMAD :**
|
||||
1. Architecture Technique (à partir des FRs/NFRs)
|
||||
2. Epics & User Stories (à partir des FRs)
|
||||
3. Développement itératif
|
||||
|
||||
---
|
||||
|
||||
*Document généré via workflow BMAD create-prd — 2026-02-18*
|
||||
@@ -0,0 +1,165 @@
|
||||
---
|
||||
stepsCompleted: [1, 2, 3, 4, 5]
|
||||
inputDocuments:
|
||||
- README.md
|
||||
- frontend/README.md
|
||||
date: 2026-02-18
|
||||
author: Sepehr
|
||||
---
|
||||
|
||||
# Product Brief: office_translator
|
||||
|
||||
<!-- Content will be appended sequentially through collaborative workflow steps -->
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Office Translator doit faire l'objet d'une **refonte complète** pour aligner le produit sur les vrais besoins : une API et une interface de traduction de documents (Excel, Word, PowerPoint) **robustes**, **sécurisées** et **maintenables**. La vision porte sur une simplification du scope (abandon des LLMs, focus sur la traduction classique), une révision de l'UX, un backend épuré sans code mort ni fonctionnalités superflues, et une base technique solide pour la suite. L'application est destinée à être **déployée en production** avec un **système d'abonnement** (monétisation) ; le rôle **admin** est **essentiel** au bon fonctionnement et doit être inclus dans la refonte.
|
||||
|
||||
---
|
||||
|
||||
## Core Vision
|
||||
|
||||
### Problem Statement
|
||||
|
||||
L'état actuel du logiciel accumule de la dette technique, des fonctionnalités peu ou plus pertinentes (dont la gestion multi-LLMs) et une expérience utilisateur à revoir. Le backend et le frontend méritent une refonte pour atteindre un niveau de robustesse et de sécurité adapté à un usage sérieux (y compris SaaS), tout en réduisant la complexité pour les mainteneurs et les utilisateurs.
|
||||
|
||||
### Problem Impact
|
||||
|
||||
Sans refonte : maintenance coûteuse, risques de bugs et de failles, complexité inutile (ex. gestion des LLMs) qui distrait de la valeur principale (traduction fiable avec préservation du format). Les utilisateurs et les développeurs subissent une UX et une codebase en dessous des objectifs de qualité et de sécurité.
|
||||
|
||||
### Why Existing Solutions Fall Short
|
||||
|
||||
La solution actuelle mélange trop de fournisseurs (Google, Ollama, WebLLM, DeepL, LibreTranslate, OpenAI) et une couche LLM (prompts, glossaires, modèles vision) qui complique le cœur métier. Les parties « traduction classique » et « préservation du format » sont la vraie valeur ; le reste ajoute de la surface d'attaque et du code mort ou peu pertinent sans apport proportionnel.
|
||||
|
||||
### Proposed Solution
|
||||
|
||||
- **Refonte backend** : simplifier et sécuriser. Conserver et renforcer la traduction via fournisseurs classiques (Google, DeepL, LibreTranslate, etc.) et **retirer complètement la gestion des LLMs** (Ollama, WebLLM, OpenAI). Supprimer le code mort et les fonctionnalités non pertinentes.
|
||||
- **Refonte frontend / UX** : revoir l’expérience utilisateur de bout en bout pour qu’elle soit claire, cohérente et orientée traduction de documents.
|
||||
- **Robustesse et sécurité** : renforcer la validation, la gestion des erreurs, les en-têtes de sécurité, l’auth admin, et les bonnes pratiques (rate limiting, nettoyage des fichiers, logs).
|
||||
|
||||
### Key Differentiators
|
||||
|
||||
- **Focus traduction documentaire** : un produit centré sur la traduction de documents Office avec préservation du format, sans la complexité des LLMs.
|
||||
- **Codebase épurée** : moins de surface d’attaque, moins de chemins de code inutiles, maintenance et évolution plus simples.
|
||||
- **Robustesse et sécurité** : architecture et pratiques pensées pour la fiabilité et un déploiement SaaS serein.
|
||||
|
||||
---
|
||||
|
||||
## Target Users
|
||||
|
||||
### Primary Users
|
||||
|
||||
**Mainteneur / utilisateur principal (vous)**
|
||||
- Contexte : utilisation et maintenance du produit au quotidien.
|
||||
- Problème vécu : la logique de certains enchaînements est difficile à suivre ; des textes sont mal placés ou dupliqués (deux versions du même texte), ce qui nuit à la cohérence. Besoin de retrouver facilement les informations et de comprendre les flux.
|
||||
- Objectif de succès : une interface et une codebase où les parcours sont clairs, les textes sont unifiés et cohérents, et les informations sont faciles à trouver. Les performances doivent être améliorées **sans dégrader** la qualité actuelle (traduction correcte et préservation du format). Les prompts système liés à la traduction doivent être revus pour plus de pertinence et de cohérence.
|
||||
|
||||
**Utilisateur final (personne qui traduit des documents)**
|
||||
- Contexte : utilisation de l’API ou du frontend pour traduire des documents Office.
|
||||
- Besoin : trouver facilement les informations (options, statut, aide), comprendre les étapes sans ambiguïté, obtenir un résultat fiable et rapide.
|
||||
- Objectif de succès : une expérience fluide, des libellés et parcours cohérents, pas de doublons ni de textes contradictoires.
|
||||
|
||||
**Admin (rôle essentiel)**
|
||||
- Contexte : exploitation et pilotage de l’application en production ; rôle **indispensable** au bon fonctionnement du service.
|
||||
- Besoin : surveiller la santé du système (santé, disque, mémoire), gérer le nettoyage des fichiers, suivre les limites de débit et l’usage, et — dans le cadre d’un **modèle SaaS avec abonnements** — superviser ou gérer les abonnements et l’activité.
|
||||
- Objectif de succès : un tableau de bord admin robuste, sécurisé et cohérent avec le reste de l’UX, permettant de faire tourner l’application et le business sereinement. La refonte doit **inclure** l’admin, pas le traiter en option.
|
||||
|
||||
### Secondary Users
|
||||
|
||||
Aucun autre segment secondaire prioritaire pour cette refonte ; les trois rôles ci-dessus (mainteneur, utilisateur final, admin) couvrent le cœur du produit.
|
||||
|
||||
### User Journey
|
||||
|
||||
- **Découverte / prise en main** : comprendre rapidement à quoi sert le produit et comment lancer une traduction.
|
||||
- **Usage courant** : déposer un document, choisir la langue et les options (sans confusion entre plusieurs versions de texte), lancer la traduction, récupérer le fichier.
|
||||
- **Succès** : document traduit fidèlement (format préservé), sans se heurter à des incohérences de libellés ou à une logique d’enchaînement obscure.
|
||||
- **Contraintes à respecter** : améliorer les performances tout en conservant le comportement actuel qui « fonctionne bien et traduit bien les documents en gardant la forme initiale ». Revoir les prompts système pour la traduction.
|
||||
|
||||
---
|
||||
|
||||
## Deployment & Monetization (à ne pas oublier)
|
||||
|
||||
- **Déploiement** : l’application est destinée à être **déployée en production** ; la refonte doit tenir compte du déploiement (sécurité, config, monitoring, admin).
|
||||
- **Monétisation** : objectif de **gagner de l’argent** avec le produit ; un **système d’abonnement** existe ou est prévu. La refonte doit préserver ou renforcer la capacité à facturer (abonnements, limites, usage) et à faire fonctionner l’admin en support de ce modèle business.
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### Succès côté utilisateur
|
||||
|
||||
L’application **réussit** pour un utilisateur quand :
|
||||
- **Rapidité** : la traduction se fait rapidement (performance).
|
||||
- **Qualité** : la personne obtient un document **très bien traduit**, au point de **ne pas avoir à faire de modifications elle-même** (qualité « prête à l’emploi »).
|
||||
- **Recommandation** : l’utilisateur est **content au point de faire de la pub** pour l’application dans son entourage (bouche-à-oreille, recommandation).
|
||||
|
||||
En résumé : traduction rapide + qualité suffisante du premier coup + satisfaction qui pousse à recommander.
|
||||
|
||||
### Business Objectives
|
||||
|
||||
Les objectifs business précis (revenus, nombre d’abonnés, horizons 3 mois / 12 mois) ne sont pas fixés aujourd’hui et seront à affiner au fil du déploiement et des retours terrain (« pas de boule de cristal »). La refonte doit en revanche **rendre possible** la monétisation (abonnements) et un pilotage via l’admin, pour que ces métriques puissent être définies et suivies plus tard.
|
||||
|
||||
### Key Performance Indicators
|
||||
|
||||
- **Utilisateur** : temps de traduction (à améliorer vs. aujourd’hui), qualité perçue (pas / peu de retouches), intention de recommander ou retours qualitatifs du type « j’en ai parlé autour de moi ».
|
||||
- **Business** : indicateurs à définir lorsque le déploiement et le modèle d’abonnement seront en place (ex. abonnés actifs, revenus récurrents, disponibilité).
|
||||
|
||||
---
|
||||
|
||||
## MVP Scope
|
||||
|
||||
### Objectif de cette version
|
||||
|
||||
**Refactoriser et améliorer le code actuel, puis déployer.** Une version V2 est envisagée plus tard ; pour l’instant, livrer cette version refondue, robuste et prête pour la production et les abonnements.
|
||||
|
||||
### Core Features (dans le MVP)
|
||||
|
||||
- **Backend** : code refactorisé et épuré (suppression du code mort, sortie des LLMs). Traduction via fournisseurs classiques (Google, DeepL, LibreTranslate, etc.) avec préservation du format. Performance améliorée sans régression sur la qualité de traduction. Configuration centralisée (ex. Pydantic BaseSettings), gestion d’erreurs et validation renforcées.
|
||||
- **Frontend / UX** : parcours clairs, textes cohérents (une seule version par message), informations faciles à trouver. Alignement avec les bonnes pratiques Next.js (performance, Core Web Vitals).
|
||||
- **Admin** : tableau de bord essentiel au bon fonctionnement (santé, disque, mémoire, rate limit, nettoyage, abonnements si déjà en place). Inclus dans la refonte, pas en option.
|
||||
- **Sécurité & déploiement** : rate limiting adapté au SaaS, en-têtes de sécurité, auth admin robuste, logs structurés. Prêt pour un déploiement production et un modèle abonnements.
|
||||
|
||||
### Out of Scope for MVP
|
||||
|
||||
- **LLMs** : retirés complètement (Ollama, WebLLM, OpenAI) dans cette version.
|
||||
- **V2** : nouvelles fonctionnalités majeures ou nouveaux marchés sont hors scope ; focus sur refonte + déploiement de l’existant amélioré.
|
||||
|
||||
### MVP Success Criteria
|
||||
|
||||
- Code actuel refactorisé et amélioré ; déploiement réussi.
|
||||
- Traduction rapide et de qualité (document bien traduit, pas de retouches nécessaires), format préservé.
|
||||
- Utilisateur et admin peuvent accomplir leurs tâches sans confusion (logique des flux, textes cohérents).
|
||||
- Base solide pour activer / faire évoluer le système d’abonnement et mesurer les KPIs plus tard.
|
||||
|
||||
### Future Vision (V2 et au-delà)
|
||||
|
||||
- V2 : nouvelles capacités, nouveaux segments ou intégrations, selon les retours et les métriques post-déploiement.
|
||||
- Évolution du produit guidée par l’usage réel et les objectifs business affinés progressivement.
|
||||
|
||||
---
|
||||
|
||||
## Propositions d'amélioration (à considérer)
|
||||
|
||||
Ces pistes s’appuient sur le brief, la structure actuelle du projet et des bonnes pratiques (FastAPI, Next.js, SaaS). À prioriser selon le temps et les objectifs.
|
||||
|
||||
### Backend (FastAPI)
|
||||
|
||||
- **Structure par domaine** : grouper par domaine métier (ex. `translation/`, `admin/`, `auth/`, `subscription/`) avec router, schemas, service, dépendances par domaine, plutôt que tout en `main.py`, pour une base plus lisible et évolutive.
|
||||
- **Configuration** : centraliser la config dans un module Pydantic `BaseSettings` (`.env`, validation des types), et y déplacer les variables admin / Redis / rate limit pour éviter les `os.getenv` dispersés.
|
||||
- **Async** : privilégier l’async de bout en bout (routes, services) et réserver le thread pool aux appels sync inévitables (ex. certaines libs de documents) pour de meilleures perfs sous charge.
|
||||
- **Sécurité** : garder rate limiting (token bucket / sliding window), CORS strict en prod, secrets hors du code. Envisager des limites par abonnement (tier) et un circuit breaker en cas de surcharge ou timeout fournisseur de traduction.
|
||||
- **Observabilité** : logs structurés (déjà en partie en place), métriques (ex. temps de traduction, erreurs par endpoint), et optionnellement health checks détaillés pour le déploiement.
|
||||
|
||||
### Frontend (Next.js)
|
||||
|
||||
- **Performance** : viser de bons Core Web Vitals (LCP < 2,5 s, INP < 200 ms, CLS < 0,1). Utiliser `next/image` et `next/font`, Server Components par défaut, `'use client'` uniquement où nécessaire. Analyser le bundle avec `@next/bundle-analyzer` et réduire les dépendances lourdes ou dupliquées.
|
||||
- **UX et cohérence** : un seul libellé par concept (plus de deux versions du même texte). Parcours clairs : upload → options → traduction → téléchargement. Placeholder et états de chargement explicites pour éviter les décalages de layout (CLS).
|
||||
- **Admin** : même langage visuel et mêmes patterns que le reste de l’app ; navigation et hiérarchie d’information claires pour que l’admin trouve rapidement les infos (santé, usage, abonnements).
|
||||
|
||||
### SaaS & déploiement
|
||||
|
||||
- **Rate limiting / quotas** : distinguer limites court terme (burst) et quotas long terme (ex. traductions/mois par abonnement). Documenter les limites dans l’API et les refléter dans l’admin.
|
||||
- **Abonnements** : s’assurer que le modèle abonnements (déjà présent en base) est bien branché à l’auth et aux limites d’usage, et que l’admin peut suivre l’activité et les comptes.
|
||||
- **CI/CD et déploiement** : pipeline de build + tests + déploiement (ex. Docker, reverse proxy HTTPS). Checklist pré-déploiement : secrets, CORS, HSTS si HTTPS, rotation des logs.
|
||||
|
||||
Ces propositions peuvent alimenter un backlog de tâches techniques une fois le brief validé.
|
||||
Reference in New Issue
Block a user