Files
office_translator/_bmad-output/implementation-artifacts/3-5-api-versioning-api-v1.md
Sepehr Ramezani 26bd096a06 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>
2026-04-25 15:01:47 +02:00

16 KiB

Story 3.5: API Versioning /api/v1/

Status: done

Story

En tant que Développeur, Je veux que tous les endpoints API soient préfixés avec /api/v1/, de sorte que les futures versions de l'API puissent coexister sans casser les clients existants.

Acceptance Criteria

  1. Préfixe Obligatoire: Tous les endpoints API sont montés sous /api/v1/ prefix. (FR33)
  2. Endpoints Non-Versionnés: Les endpoints sans préfixe de version retournent 404 (sauf health check et documentation).
  3. Documentation OpenAPI: La version est documentée dans la spécification OpenAPI (title, version, description).
  4. Rétrocompatibilité: Les clients existants utilisant /api/v1/* ne sont pas affectés.
  5. Health Check Préservé: /health et /ready restent accessibles sans préfixe pour les probes Kubernetes.
  6. Documentation Accessible: /docs (Swagger UI) et /redoc restent accessibles sans préfixe.

Tasks / Subtasks

  • Task 1: Auditer les Endpoints Non-Versionnés (AC: #1, #2)

    • 1.1 Lister tous les endpoints dans main.py qui ne sont pas sous /api/v1/
    • 1.2 Identifier les endpoints à migrer vs à préserver (health, docs)
    • 1.3 Documenter la liste des endpoints à déplacer
  • Task 2: Créer un Routeur Racine API v1 (AC: #1)

    • 2.1 Créer routes/api_v1_router.py avec un routeur principal pour /api/v1
    • 2.2 Inclure tous les sous-routeurs (translate, auth, api-keys, admin)
    • 2.3 Configurer les tags OpenAPI pour la documentation
  • Task 3: Migrer les Endpoints de main.py (AC: #1, #2)

    • 3.1 Déplacer /languages vers /api/v1/languages
    • 3.2 Déplacer /translate vers /api/v1/translate (déjà fait via translate_routes.py)
    • 3.3 Déplacer /translate-batch vers /api/v1/translate/batch
    • 3.4 Déplacer /download/{filename} vers /api/v1/download/{filename}
    • 3.5 Déplacer /extract-texts vers /api/v1/extract-texts
    • 3.6 Déplacer /reconstruct-document vers /api/v1/reconstruct-document
    • 3.7 Déplacer /ollama/models vers /api/v1/ollama/models
    • 3.8 Déplacer /ollama/configure vers /api/v1/ollama/configure
    • 3.9 Déplacer /rate-limit/status vers /api/v1/rate-limit/status
    • 3.10 Déplacer /admin/* vers /api/v1/admin/*
    • 3.11 Déplacer /metrics vers /api/v1/metrics
  • Task 4: Configurer les Exceptions de Versioning (AC: #5, #6)

    • 4.1 Garder /health accessible sans préfixe (Kubernetes probe)
    • 4.2 Garder /ready accessible sans préfixe (Kubernetes probe)
    • 4.3 Garder /docs accessible sans préfixe (Swagger UI)
    • 4.4 Garder /redoc accessible sans préfixe (ReDoc)
    • 4.5 Garder /openapi.json accessible sans préfixe
    • 4.6 Optionnel: Garder / comme endpoint info avec redirect vers /docs
  • Task 5: Mettre à jour la Documentation OpenAPI (AC: #3)

    • 5.1 Vérifier que config.API_VERSION est utilisé dans FastAPI app
    • 5.2 Ajouter la description de versioning dans la description de l'API
    • 5.3 Documenter les endpoints versionnés dans les tags OpenAPI
  • Task 6: Nettoyer main.py (AC: #1, #2)

    • 6.1 Supprimer les endpoints déplacés de main.py
    • 6.2 Garder uniquement les endpoints exception (health, docs, root)
    • 6.3 Inclure le routeur API v1 principal
  • Task 7: Ajouter les Tests (AC: Tous)

    • 7.1 Test endpoint versionné accessible (/api/v1/health ou /api/v1/languages)
    • 7.2 Test endpoint non-versionné retourne 404 (sauf exceptions)
    • 7.3 Test health check accessible sans préfixe
    • 7.4 Test documentation accessible sans préfixe
    • 7.5 Test tous les endpoints migrés fonctionnent

Dev Notes

État Actuel du Versioning

Endpoints DÉJÀ versionnés (via routeurs):

  • POST /api/v1/translate - translate_routes.py
  • GET /api/v1/translations/{id} - translate_routes.py
  • GET /api/v1/download/{job_id} - translate_routes.py
  • POST /api/v1/auth/register - auth_routes.py
  • POST /api/v1/auth/login - auth_routes.py
  • POST /api/v1/api-keys - api_key_routes.py
  • GET /api/v1/api-keys - api_key_routes.py
  • DELETE /api/v1/api-keys/{key_id} - api_key_routes.py
  • DELETE /api/v1/admin/api-keys/{key_id} - admin_routes.py

Endpoints NON versionnés (dans main.py à migrer):

Endpoint Migration
/ Garder ou redirect vers /docs
/health GARDER (K8s probe)
/ready GARDER (K8s probe)
/languages /api/v1/languages
/translate → Supprimer (doublon avec /api/v1/translate)
/translate-batch /api/v1/translate/batch
/download/{filename} → Supprimer (doublon avec /api/v1/download/{job_id})
/extract-texts /api/v1/extract-texts
/reconstruct-document /api/v1/reconstruct-document
/ollama/models /api/v1/ollama/models
/ollama/configure /api/v1/ollama/configure
/metrics /api/v1/metrics
/rate-limit/status /api/v1/rate-limit/status
/admin/login /api/v1/admin/login
/admin/logout /api/v1/admin/logout
/admin/verify /api/v1/admin/verify
/admin/dashboard /api/v1/admin/dashboard
/admin/users /api/v1/admin/users
/admin/users/{user_id} /api/v1/admin/users/{user_id}
/admin/stats /api/v1/admin/stats
/admin/cleanup/trigger /api/v1/admin/cleanup/trigger
/admin/files/tracked /api/v1/admin/files/tracked
/admin/config/provider /api/v1/admin/config/provider
/cleanup/{filename} /api/v1/cleanup/{filename}

Architecture Proposée

main.py
├── /health (exception - K8s probe)
├── /ready (exception - K8s probe)
├── /docs (exception - Swagger UI)
├── /redoc (exception - ReDoc)
├── /openapi.json (exception - OpenAPI spec)
├── / (optionnel: redirect vers /docs)
└── include_router(api_v1_router)  # Tout le reste sous /api/v1/

routes/
├── api_v1_router.py      # NOUVEAU - Routeur principal /api/v1
│   ├── include_router(translate_v1_router)
│   ├── include_router(auth_v1_router)
│   ├── include_router(api_key_router)
│   ├── include_router(admin_v1_router)  # NOUVEAU
│   └── include_router(legacy_router)    # NOUVEAU
├── admin_routes.py       # NOUVEAU - Endpoints admin versionnés
├── legacy_routes.py      # NOUVEAU - Endpoints legacy versionnés
├── translate_routes.py   # Existant
├── auth_routes.py        # Existant
└── api_key_routes.py     # Existant

Patterns à Suivre

Pattern de Routeur Principal:

# routes/api_v1_router.py
from fastapi import APIRouter

router = APIRouter(tags=["API v1"])

# Inclure les sous-routeurs
from routes.translate_routes import router_v1 as translate_router
from routes.auth_routes import router_v1 as auth_router
from routes.api_key_routes import router as api_key_router

router.include_router(translate_router, tags=["Translation"])
router.include_router(auth_router, tags=["Authentication"])
router.include_router(api_key_router, tags=["API Keys"])

Pattern d'Endpoint Admin Versionné:

# routes/admin_routes.py
from fastapi import APIRouter

router = APIRouter(prefix="/admin", tags=["Admin"])

@router.post("/login")
async def admin_login(...):
    ...

@router.get("/dashboard")
async def get_admin_dashboard(...):
    ...

Configuration FastAPI:

# main.py
from routes.api_v1_router import router as api_v1_router

app = FastAPI(
    title="Office Translator API",
    version="1.0.0",
    description="API de traduction de documents Office. Tous les endpoints sont préfixés avec /api/v1/.",
)

# Endpoints exception (sans préfixe)
@app.get("/health")
async def health_check():
    ...

# Inclure le routeur principal
app.include_router(api_v1_router)

Structure de Fichiers

routes/
├── __init__.py
├── api_v1_router.py      # CRÉÉ - Routeur principal
├── admin_routes.py       # CRÉÉ - Endpoints admin versionnés
├── legacy_routes.py      # CRÉÉ - Endpoints migrés de main.py
├── translate_routes.py   # Existant - Pas de changement
├── auth_routes.py        # Existant - Pas de changement
└── api_key_routes.py     # Existant - Pas de changement

main.py                   # MODIFIÉ - Nettoyer et inclure api_v1_router
config.py                 # MODIFIÉ - Description mise à jour
tests/
└── test_story_3_5_api_versioning.py  # CRÉÉ

Project Structure Notes

  • Le projet suit une structure plate (pas de dossier backend/app/)
  • Les routeurs sont dans routes/
  • Les modèles sont dans database/models.py
  • Les services sont dans services/
  • Les tests sont dans tests/

Références

  • [Source: _bmad-output/planning-artifacts/epics.md#Story 3.5]
  • [Source: _bmad-output/planning-artifacts/architecture.md#API & Communication Patterns]
  • [Source: main.py - Endpoints actuels]
  • [Source: routes/translate_routes.py - Pattern de routeur versionné]

Intelligence des Stories Précédentes (Epic 3)

Story 3.1 (API Key Generation) - Enseignements

  1. Routeur api_key_routes.py utilise prefix="/api/v1/api-keys"
  2. Pattern de réponse {data: {...}, meta: {...}} établi
  3. Tests complets avec fixtures dans tests/conftest.py

Story 3.2 (API Key Revocation User) - Enseignements

  1. Soft delete avec is_active=False
  2. Fonction get_user_by_api_key dans services/auth_service.py
  3. Format d'erreur structuré {error, message, details?}

Story 3.3 (Admin API Key Revocation) - Enseignements

  1. Routes admin dans main.py - migré vers routes/admin_routes.py
  2. Dépendance require_admin pour l'authentification admin
  3. Audit logging avec logger.info()

Story 3.4 (API Auth X-API-Key) - Enseignements

  1. Coexistence JWT + API Key dans get_authenticated_user
  2. Middleware d'auth dans routes/translate_routes.py
  3. Priorité API key sur JWT si les deux présents

Intelligence Git (Commits Récents)

Derniers commits pertinents:

  • 3d37ce4: PostgreSQL database infrastructure
  • c4d6cae: Redis sessions, security hardening
  • dfd45d9: Admin login endpoint

Patterns identifiés:

  • Routeurs avec APIRouter(prefix="/api/v1")
  • Tests avec pytest dans tests/
  • Fixtures dans tests/conftest.py

Contexte Métier

Epic 3: API & Automation (Pro)

Cette story est la cinquième de l'Epic 3 qui permet aux utilisateurs Pro d'automatiser les traductions:

  1. API Keys - Génération (Story 3.1 )
  2. API Keys - Révocation User (Story 3.2 )
  3. API Keys - Révocation Admin (Story 3.3 )
  4. Authentification X-API-Key (Story 3.4 )
  5. API Versioning (cette story - COMPLETE)
  6. Documentation OpenAPI (Story 3.6 - ready-for-dev)
  7. Webhooks (Stories 3.7-3.8 - backlog)
  8. Glossaires (Stories 3.9-3.10 - backlog)
  9. Custom Prompts (Stories 3.11-3.12 - backlog)

Valeur Business

Le versioning d'API est critique pour:

  • Évolutivité: Pouvoir faire évoluer l'API sans casser les clients existants
  • Documentation: Clarté sur la version utilisée
  • Migration: Permettre une transition douce lors de changements majeurs
  • Professionalisme: Standard de l'industrie pour les APIs REST

Dépendances

  • Stories 3.1-3.4 (prérequis): Endpoints déjà versionnés
  • Story 3.6 (impact): Documentation OpenAPI à mettre à jour

Guardrails Développeur

À NE PAS FAIRE

  1. NE PAS supprimer les endpoints health/ready (K8s probes)
  2. NE PAS supprimer l'accès à /docs et /redoc
  3. NE PAS casser les clients existants utilisant /api/v1/*
  4. NE PAS dupliquer le code - utiliser include_router
  5. NE PAS oublier de tester tous les endpoints migrés
  6. NE PAS modifier les routeurs existants (translate_routes.py, auth_routes.py, api_key_routes.py)

À FAIRE

  1. TOUJOURS préfixer les nouveaux endpoints avec /api/v1/
  2. TOUJOURS garder health/ready accessibles sans préfixe
  3. TOUJOURS tester que les endpoints non-versionnés retournent 404
  4. TOUJOURS documenter la version dans OpenAPI
  5. TOUJOURS utiliser include_router pour composer les routeurs
  6. CRÉER un routeur principal api_v1_router.py
  7. CRÉER un routeur admin admin_routes.py

Dev Agent Record

Agent Model Used

Claude Sonnet 4

Debug Log References

  • App import successful after refactoring
  • All 31 versioning tests pass
  • Updated existing tests to use versioned endpoints
  • Patch paths updated for translator mocks

Completion Notes List

  • Analyse exhaustive du contexte terminée - guide complet créé pour le développeur
  • Endpoints existants analysés (versionnés et non-versionnés)
  • Architecture proposée avec routeur principal et sous-routeurs
  • Liste complète des endpoints à migrer documentée
  • Exceptions documentées (health, ready, docs, redoc)
  • Routes api_v1_router.py créé - agrège tous les sous-routeurs
  • Routes admin_routes.py créé - tous les endpoints admin sous /api/v1/admin/
  • Routes legacy_routes.py créé - endpoints migrés (languages, ollama, metrics, etc.)
  • main.py nettoyé - ne contient plus que les exceptions (health, ready, root)
  • Config.py mis à jour avec description mentionnant /api/v1
  • Tests complets créés dans tests/test_story_3_5_api_versioning.py
  • Tests existants mis à jour pour utiliser les endpoints versionnés
  • Ancien auth_router marqué DEPRECATED - non importé, conservé pour référence

Code Review Fixes Applied (2026-02-22)

  • 🔧 Sécurité: Suppression du mot de passe admin par défaut "changeme123"
  • 🔧 Stripe webhook migré vers /api/v1/auth/webhook/stripe
  • 🔧 Valeurs hardcodées remplacées par config (metrics, rate-limit/status)
  • 🔧 Tests ajoutés pour endpoints manquants (extract-texts, reconstruct, batch, download, cleanup)
  • 🔧 Ancien router /api/auth marqué DEPRECATED avec documentation

File List

  • routes/api_v1_router.py - CRÉÉ - Routeur principal /api/v1
  • routes/admin_routes.py - CRÉÉ - Endpoints admin versionnés
  • routes/legacy_routes.py - CRÉÉ - Endpoints migrés de main.py
  • main.py - MODIFIÉ - Nettoyé et inclut api_v1_router uniquement
  • config.py - MODIFIÉ - Description mise à jour avec mention /api/v1
  • tests/test_story_3_5_api_versioning.py - CRÉÉ - 31 tests complets
  • tests/test_admin_tier_change.py - MODIFIÉ - URLs et patches mis à jour
  • tests/test_story_3_3_admin_api_key_revocation.py - MODIFIÉ - URLs et patches mis à jour
  • tests/test_auth_register.py - MODIFIÉ - Test legacy path skipped

Change Log

  • 2026-02-22: Story créée avec contexte complet (endpoints à migrer, architecture proposée, code suggéré)
  • 2026-02-22: Implémentation complète - tous les endpoints migrés sous /api/v1/, tests passants

Checklist de Validation

Avant de marquer cette story comme terminée, vérifier:

  • Tous les endpoints API sont sous /api/v1/
  • Les endpoints non-versionnés retournent 404 (sauf exceptions)
  • /health et /ready sont accessibles sans préfixe
  • /docs et /redoc sont accessibles sans préfixe
  • La version est documentée dans OpenAPI
  • Les clients existants utilisant /api/v1/* ne sont pas affectés
  • Tous les tests passent
  • Le routeur principal api_v1_router.py est créé
  • Le routeur admin admin_routes.py est créé
  • main.py est nettoyé et ne contient que les endpoints exception