feat: homelab deployment - NPM + IONOS DNS + monitoring + NAS backup
- Restructured docker-compose for Nginx Proxy Manager (no custom nginx) - Added domain wordly.art configuration - Added Prometheus + Grafana monitoring stack with pre-configured dashboards - Added PostgreSQL backup script to NAS (daily/weekly/monthly rotation) - Added alert rules for backend, system, and Docker metrics - Updated deployment guide for NPM + IONOS DNS homelab setup - Added marketing plan document - PDF translator and watermark support - Enhanced middleware, routes, and translator modules Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -37,28 +37,29 @@ import os
|
||||
# or google/gemini-3-flash ($0.15 / $0.60)
|
||||
PLANS = {
|
||||
PlanType.FREE: {
|
||||
"name": "Gratuit",
|
||||
"name": "Free",
|
||||
"price_monthly": 0,
|
||||
"price_yearly": 0,
|
||||
"docs_per_month": 5,
|
||||
"max_pages_per_doc": 15,
|
||||
"docs_per_month": 2,
|
||||
"max_pages_per_doc": 10,
|
||||
"max_file_size_mb": 5,
|
||||
"max_chars_per_month": 50_000,
|
||||
"max_chars_per_month": 20_000,
|
||||
"providers": ["google"],
|
||||
"features": [
|
||||
"5 documents / mois",
|
||||
"Jusqu'à 15 pages par document",
|
||||
"Google Traduction inclus",
|
||||
"Toutes les langues (130+)",
|
||||
"Support communautaire",
|
||||
"pricing.plans.free.feat1",
|
||||
"pricing.plans.free.feat2",
|
||||
"pricing.plans.free.feat3",
|
||||
"pricing.plans.free.feat4",
|
||||
"pricing.plans.free.feat5",
|
||||
],
|
||||
"ai_translation": False,
|
||||
"api_access": False,
|
||||
"priority_processing": False,
|
||||
"watermark": True,
|
||||
"stripe_price_id_monthly": None,
|
||||
"stripe_price_id_yearly": None,
|
||||
"highlight": None,
|
||||
"description": "Parfait pour découvrir l'application",
|
||||
"description": "pricing.plans.free.description",
|
||||
"badge": None,
|
||||
},
|
||||
PlanType.STARTER: {
|
||||
@@ -71,12 +72,12 @@ PLANS = {
|
||||
"max_chars_per_month": 500_000,
|
||||
"providers": ["google", "deepl"],
|
||||
"features": [
|
||||
"50 documents / mois",
|
||||
"Jusqu'à 50 pages par document",
|
||||
"Google Traduction + DeepL",
|
||||
"Fichiers jusqu'à 10 Mo",
|
||||
"Support par e-mail",
|
||||
"Historique 30 jours",
|
||||
"pricing.plans.starter.feat1",
|
||||
"pricing.plans.starter.feat2",
|
||||
"pricing.plans.starter.feat3",
|
||||
"pricing.plans.starter.feat4",
|
||||
"pricing.plans.starter.feat5",
|
||||
"pricing.plans.starter.feat6",
|
||||
],
|
||||
"ai_translation": False,
|
||||
"api_access": False,
|
||||
@@ -84,7 +85,7 @@ PLANS = {
|
||||
"stripe_price_id_monthly": os.getenv("STRIPE_PRICE_STARTER_MONTHLY", ""),
|
||||
"stripe_price_id_yearly": os.getenv("STRIPE_PRICE_STARTER_YEARLY", ""),
|
||||
"highlight": None,
|
||||
"description": "Pour les particuliers et petits projets",
|
||||
"description": "pricing.plans.starter.description",
|
||||
"badge": None,
|
||||
},
|
||||
PlanType.PRO: {
|
||||
@@ -98,14 +99,14 @@ PLANS = {
|
||||
"providers": ["google", "google_cloud", "deepl", "openrouter"],
|
||||
"ai_model_essential": "deepseek/deepseek-v3.2",
|
||||
"features": [
|
||||
"200 documents / mois",
|
||||
"Jusqu'à 200 pages par document",
|
||||
"Traduction IA Essentielle incluse (DeepSeek V3.2)",
|
||||
"Google Traduction + DeepL",
|
||||
"Fichiers jusqu'à 25 Mo",
|
||||
"Glossaires personnalisés",
|
||||
"Support prioritaire par e-mail",
|
||||
"Historique 90 jours",
|
||||
"pricing.plans.pro.feat1",
|
||||
"pricing.plans.pro.feat2",
|
||||
"pricing.plans.pro.feat3",
|
||||
"pricing.plans.pro.feat4",
|
||||
"pricing.plans.pro.feat5",
|
||||
"pricing.plans.pro.feat6",
|
||||
"pricing.plans.pro.feat7",
|
||||
"pricing.plans.pro.feat8",
|
||||
],
|
||||
"ai_translation": True,
|
||||
"ai_tier": "essential",
|
||||
@@ -113,9 +114,9 @@ PLANS = {
|
||||
"priority_processing": True,
|
||||
"stripe_price_id_monthly": os.getenv("STRIPE_PRICE_PRO_MONTHLY", ""),
|
||||
"stripe_price_id_yearly": os.getenv("STRIPE_PRICE_PRO_YEARLY", ""),
|
||||
"highlight": "Le plus populaire",
|
||||
"description": "Pour les professionnels et équipes en croissance",
|
||||
"badge": "POPULAIRE",
|
||||
"highlight": "pricing.plans.pro.highlight",
|
||||
"description": "pricing.plans.pro.description",
|
||||
"badge": "POPULAR",
|
||||
},
|
||||
PlanType.BUSINESS: {
|
||||
"name": "Business",
|
||||
@@ -129,17 +130,16 @@ PLANS = {
|
||||
"ai_model_essential": "deepseek/deepseek-v3.2",
|
||||
"ai_model_premium": "anthropic/claude-3.5-haiku",
|
||||
"features": [
|
||||
"1 000 documents / mois",
|
||||
"Jusqu'à 500 pages par document",
|
||||
"Traduction IA Essentielle + Premium (Claude Haiku)",
|
||||
"Tous les fournisseurs de traduction",
|
||||
"Fichiers jusqu'à 50 Mo",
|
||||
"Accès API (10 000 appels/mois)",
|
||||
"Webhooks de notification",
|
||||
"Glossaires + Prompts personnalisés",
|
||||
"Support dédié",
|
||||
"Historique 1 an",
|
||||
"Analytiques avancées",
|
||||
"pricing.plans.business.feat1",
|
||||
"pricing.plans.business.feat2",
|
||||
"pricing.plans.business.feat3",
|
||||
"pricing.plans.business.feat4",
|
||||
"pricing.plans.business.feat5",
|
||||
"pricing.plans.business.feat6",
|
||||
"pricing.plans.business.feat7",
|
||||
"pricing.plans.business.feat8",
|
||||
"pricing.plans.business.feat9",
|
||||
"pricing.plans.business.feat10",
|
||||
],
|
||||
"ai_translation": True,
|
||||
"ai_tier": "premium",
|
||||
@@ -150,11 +150,11 @@ PLANS = {
|
||||
"stripe_price_id_monthly": os.getenv("STRIPE_PRICE_BUSINESS_MONTHLY", ""),
|
||||
"stripe_price_id_yearly": os.getenv("STRIPE_PRICE_BUSINESS_YEARLY", ""),
|
||||
"highlight": None,
|
||||
"description": "Pour les équipes et organisations",
|
||||
"description": "pricing.plans.business.description",
|
||||
"badge": None,
|
||||
},
|
||||
PlanType.ENTERPRISE: {
|
||||
"name": "Entreprise",
|
||||
"name": "Enterprise",
|
||||
"price_monthly": -1,
|
||||
"price_yearly": -1,
|
||||
"docs_per_month": -1,
|
||||
@@ -163,15 +163,14 @@ PLANS = {
|
||||
"max_chars_per_month": -1,
|
||||
"providers": ["google", "google_cloud", "deepl", "openrouter", "openrouter_premium", "openai", "zai", "custom"],
|
||||
"features": [
|
||||
"Documents illimités",
|
||||
"Tous les modèles IA (GPT-5, Claude Opus 4.6...)",
|
||||
"Déploiement on-premise ou cloud dédié",
|
||||
"SLA 99,9 % garanti",
|
||||
"Support 24/7 dédié",
|
||||
"Modèles IA personnalisés",
|
||||
"Marque blanche (white-label)",
|
||||
"Équipes illimitées",
|
||||
"Intégrations sur mesure",
|
||||
"pricing.plans.enterprise.feat1",
|
||||
"pricing.plans.enterprise.feat2",
|
||||
"pricing.plans.enterprise.feat3",
|
||||
"pricing.plans.enterprise.feat4",
|
||||
"pricing.plans.enterprise.feat5",
|
||||
"pricing.plans.enterprise.feat6",
|
||||
"pricing.plans.enterprise.feat7",
|
||||
"pricing.plans.enterprise.feat8",
|
||||
],
|
||||
"ai_translation": True,
|
||||
"ai_tier": "custom",
|
||||
@@ -182,8 +181,8 @@ PLANS = {
|
||||
"stripe_price_id_monthly": None,
|
||||
"stripe_price_id_yearly": None,
|
||||
"highlight": None,
|
||||
"description": "Solutions sur mesure pour grandes organisations",
|
||||
"badge": "SUR DEVIS",
|
||||
"description": "pricing.plans.enterprise.description",
|
||||
"badge": "ON REQUEST",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -243,13 +242,13 @@ class UserCreate(BaseModel):
|
||||
def validate_password_strength(cls, v: str) -> str:
|
||||
"""Validate password meets minimum security requirements."""
|
||||
if len(v) < 8:
|
||||
raise ValueError("Le mot de passe doit contenir au moins 8 caractères")
|
||||
raise ValueError("Password must be at least 8 characters")
|
||||
if not re.search(r"[A-Z]", v):
|
||||
raise ValueError("Le mot de passe doit contenir au moins une majuscule")
|
||||
raise ValueError("Password must contain at least one uppercase letter")
|
||||
if not re.search(r"[a-z]", v):
|
||||
raise ValueError("Le mot de passe doit contenir au moins une minuscule")
|
||||
raise ValueError("Password must contain at least one lowercase letter")
|
||||
if not re.search(r"[0-9]", v):
|
||||
raise ValueError("Le mot de passe doit contenir au moins un chiffre")
|
||||
raise ValueError("Password must contain at least one digit")
|
||||
return v
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user