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:
2026-05-10 11:43:28 +02:00
parent 16ac7ca2b9
commit ce8e150a61
110 changed files with 6935 additions and 4301 deletions

View File

@@ -40,7 +40,7 @@ def _validate_uuid(prompt_id: str) -> tuple[bool, dict | None]:
except ValueError:
return False, {
"error": "INVALID_PROMPT_ID",
"message": "Format d'identifiant de prompt invalide.",
"message": "Invalid prompt ID format.",
}
@@ -122,7 +122,7 @@ async def create_prompt(
status_code=500,
content={
"error": "DATABASE_ERROR",
"message": "Une erreur est survenue lors de la création du prompt.",
"message": "An error occurred while creating the prompt.",
},
)
@@ -190,7 +190,7 @@ async def list_prompts(
status_code=500,
content={
"error": "DATABASE_ERROR",
"message": "Une erreur est survenue lors de la récupération des prompts.",
"message": "An error occurred while retrieving prompts.",
},
)
@@ -223,7 +223,7 @@ async def get_prompt(
status_code=404,
content={
"error": "PROMPT_NOT_FOUND",
"message": "Prompt introuvable ou vous n'avez pas accès à cette ressource.",
"message": "Prompt not found or you do not have access to this resource.",
},
)
@@ -240,7 +240,7 @@ async def get_prompt(
status_code=500,
content={
"error": "DATABASE_ERROR",
"message": "Une erreur est survenue.",
"message": "An error occurred.",
},
)
@@ -262,7 +262,7 @@ async def update_prompt(
status_code=400,
content={
"error": "NO_UPDATE_FIELDS",
"message": "Au moins un champ (name ou content) doit être fourni.",
"message": "At least one field (name or content) must be provided.",
},
)
@@ -283,7 +283,7 @@ async def update_prompt(
status_code=404,
content={
"error": "PROMPT_NOT_FOUND",
"message": "Prompt introuvable ou vous n'avez pas accès à cette ressource.",
"message": "Prompt not found or you do not have access to this resource.",
},
)
@@ -317,7 +317,7 @@ async def update_prompt(
status_code=500,
content={
"error": "DATABASE_ERROR",
"message": "Une erreur est survenue lors de la mise à jour.",
"message": "An error occurred while updating.",
},
)
@@ -350,7 +350,7 @@ async def delete_prompt(
status_code=404,
content={
"error": "PROMPT_NOT_FOUND",
"message": "Prompt introuvable ou vous n'avez pas accès à cette ressource.",
"message": "Prompt not found or you do not have access to this resource.",
},
)
@@ -372,6 +372,6 @@ async def delete_prompt(
status_code=500,
content={
"error": "DATABASE_ERROR",
"message": "Une erreur est survenue lors de la suppression.",
"message": "An error occurred while deleting.",
},
)