es.po 10590 lignes · 340236 octets
msgid ""
msgstr ""
"Project-Id-Version: Documentation gitrust\n"
"POT-Creation-Date: 2026-04-17T17:18:35+02:00\n"
"PO-Revision-Date: 2026-04-17T17:18:35+02:00\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: src/SUMMARY.md:1
msgid "Sommaire"
msgstr ""

#: src/SUMMARY.md:3 src/introduction.md:1
msgid "Introduction"
msgstr ""

#: src/SUMMARY.md:7 src/user_manual/index.md:1
msgid "Manuel utilisateur"
msgstr ""

#: src/SUMMARY.md:9 src/SUMMARY.md:40 src/SUMMARY.md:76
#: src/user_manual/tutorials/01-premier-pas.md:17
#: src/administration_manual/tutorials/01-installation-docker.md:17
#: src/developer_manual/tutorials/01-getting-started.md:19
#: src/developer_manual/explanation/vue-ensemble-architecture.md:5
msgid "Vue d'ensemble"
msgstr ""

#: src/SUMMARY.md:10 src/SUMMARY.md:41 src/SUMMARY.md:77
#: src/user_manual/tutorials/index.md:1
#: src/administration_manual/tutorials/index.md:1
#: src/developer_manual/tutorials/index.md:1
msgid "Tutoriels"
msgstr ""

#: src/SUMMARY.md:11
msgid "01 — Premier pas sur gitrust"
msgstr ""

#: src/SUMMARY.md:12 src/user_manual/tutorials/02-cloner-pousser.md:1
msgid "02 — Cloner et pousser du code"
msgstr ""

#: src/SUMMARY.md:13 src/user_manual/tutorials/03-collaborer.md:1
msgid "03 — Collaborer : équipes, issues, pull requests"
msgstr ""

#: src/SUMMARY.md:14 src/user_manual/tutorials/04-automatiser-ci.md:1
msgid "04 — Automatiser avec la CI"
msgstr ""

#: src/SUMMARY.md:15 src/SUMMARY.md:46 src/SUMMARY.md:81
#: src/user_manual/how-to/index.md:1
#: src/administration_manual/how-to/index.md:1
#: src/developer_manual/how-to/index.md:1
msgid "Guides pratiques"
msgstr ""

#: src/SUMMARY.md:16 src/user_manual/how-to/gerer-cles-ssh.md:1
msgid "Gérer ses clés SSH"
msgstr ""

#: src/SUMMARY.md:17 src/user_manual/how-to/configurer-2fa.md:1
msgid "Configurer la double authentification (2FA)"
msgstr ""

#: src/SUMMARY.md:18 src/user_manual/how-to/creer-personal-access-token.md:1
msgid "Créer un Personal Access Token"
msgstr ""

#: src/SUMMARY.md:19 src/user_manual/how-to/gerer-equipes-permissions.md:1
msgid "Gérer les équipes et les permissions"
msgstr ""

#: src/SUMMARY.md:20 src/user_manual/how-to/ouvrir-pull-request.md:1
msgid "Ouvrir une pull request"
msgstr ""

#: src/SUMMARY.md:21 src/user_manual/how-to/fusionner-strategies.md:1
msgid "Stratégies de fusion (ff / squash / merge commit)"
msgstr ""

#: src/SUMMARY.md:22 src/user_manual/how-to/utiliser-labels-issues.md:1
msgid "Utiliser les labels et les issues"
msgstr ""

#: src/SUMMARY.md:23 src/user_manual/how-to/importer-depot-externe.md:1
#: src/developer_manual/how-to/importer-depot-externe-code.md:1
msgid "Importer un dépôt externe"
msgstr ""

#: src/SUMMARY.md:24 src/user_manual/how-to/consulter-sbom.md:1
msgid "Consulter le SBOM d'un dépôt"
msgstr ""

#: src/SUMMARY.md:25 src/SUMMARY.md:60 src/SUMMARY.md:93
#: src/user_manual/reference/index.md:1
#: src/administration_manual/reference/index.md:1
#: src/developer_manual/reference/index.md:1
msgid "Référence"
msgstr ""

#: src/SUMMARY.md:26 src/user_manual/reference/modele-permissions.md:1
msgid "Modèle de permissions (4 rôles)"
msgstr ""

#: src/SUMMARY.md:27 src/SUMMARY.md:98
#: src/user_manual/reference/api-rest-v1.md:1
#: src/developer_manual/reference/api-rest-v1.md:1
msgid "API REST v1"
msgstr ""

#: src/SUMMARY.md:28 src/user_manual/reference/gitrust-ci-yml-schema.md:1
msgid "Schéma du fichier .gitrust-ci.yml"
msgstr ""

#: src/SUMMARY.md:29 src/user_manual/reference/markdown-et-syntaxe.md:1
msgid "Markdown et syntaxe supportée"
msgstr ""

#: src/SUMMARY.md:30 src/user_manual/reference/notifications.md:1
#: src/developer_manual/tutorials/01-getting-started.md:343
#: src/developer_manual/reference/architecture-crates.md:164
msgid "Notifications"
msgstr ""

#: src/SUMMARY.md:31 src/SUMMARY.md:66 src/SUMMARY.md:101
#: src/user_manual/explanation/index.md:1
#: src/administration_manual/explanation/index.md:1
#: src/developer_manual/explanation/index.md:1
msgid "Explication"
msgstr ""

#: src/SUMMARY.md:32 src/user_manual/explanation/modele-collaboration.md:1
msgid "Modèle de collaboration sur gitrust"
msgstr ""

#: src/SUMMARY.md:33 src/user_manual/explanation/securite-utilisateur.md:1
msgid "Sécurité côté utilisateur"
msgstr ""

#: src/SUMMARY.md:34 src/user_manual/explanation/cycle-vie-pull-request.md:1
msgid "Cycle de vie d'une pull request"
msgstr ""

#: src/SUMMARY.md:38 src/administration_manual/index.md:1
msgid "Manuel d'administration"
msgstr ""

#: src/SUMMARY.md:42
msgid "01 — Installation avec Docker"
msgstr ""

#: src/SUMMARY.md:43
#: src/administration_manual/tutorials/02-installation-systemd.md:1
msgid "02 — Installation avec systemd"
msgstr ""

#: src/SUMMARY.md:44
#: src/administration_manual/tutorials/03-premier-demarrage.md:1
msgid "03 — Premier démarrage"
msgstr ""

#: src/SUMMARY.md:45
msgid "04 — Mise en production (réseau local)"
msgstr ""

#: src/SUMMARY.md:47
#: src/administration_manual/how-to/sauvegarder-restaurer.md:1
msgid "Sauvegarder et restaurer"
msgstr ""

#: src/SUMMARY.md:48 src/administration_manual/how-to/mettre-a-jour.md:1
msgid "Mettre à jour gitrust"
msgstr ""

#: src/SUMMARY.md:49 src/administration_manual/how-to/configurer-smtp.md:1
msgid "Configurer SMTP"
msgstr ""

#: src/SUMMARY.md:50 src/administration_manual/how-to/configurer-oauth.md:1
msgid "Configurer OAuth"
msgstr ""

#: src/SUMMARY.md:51
msgid "Configurer un runner CI distant"
msgstr ""

#: src/SUMMARY.md:52
msgid "Intégrer Dependency-Track (SBOM)"
msgstr ""

#: src/SUMMARY.md:53
msgid "Durcir avec Fail2ban"
msgstr ""

#: src/SUMMARY.md:54 src/administration_manual/how-to/tuner-rate-limiting.md:1
msgid "Régler le rate limiting"
msgstr ""

#: src/SUMMARY.md:55
#: src/administration_manual/how-to/forcer-2fa-globalement.md:1
msgid "Forcer le 2FA sur toute l'instance"
msgstr ""

#: src/SUMMARY.md:56 src/administration_manual/how-to/depanner-ssh.md:1
msgid "Dépanner SSH"
msgstr ""

#: src/SUMMARY.md:57 src/administration_manual/how-to/depanner-ci.md:1
msgid "Dépanner la CI"
msgstr ""

#: src/SUMMARY.md:58
#: src/administration_manual/how-to/gerer-utilisateurs-admin.md:1
msgid "Gérer les utilisateurs (panel /admin)"
msgstr ""

#: src/SUMMARY.md:59 src/administration_manual/how-to/auditer-instance.md:1
msgid "Auditer une instance"
msgstr ""

#: src/SUMMARY.md:61
#: src/administration_manual/reference/variables-environnement.md:1
msgid "Variables d'environnement"
msgstr ""

#: src/SUMMARY.md:62
#: src/administration_manual/reference/parametres-dynamiques.md:1
msgid "Paramètres dynamiques"
msgstr ""

#: src/SUMMARY.md:63 src/SUMMARY.md:96
#: src/administration_manual/reference/schema-base-de-donnees.md:1
#: src/developer_manual/reference/schema-base-donnees.md:1
msgid "Schéma de la base de données"
msgstr ""

#: src/SUMMARY.md:64 src/administration_manual/reference/ports-et-services.md:1
msgid "Ports et services"
msgstr ""

#: src/SUMMARY.md:65
#: src/administration_manual/reference/conformite-anssi-pa074.md:1
msgid "Conformité ANSSI PA-074"
msgstr ""

#: src/SUMMARY.md:67
#: src/administration_manual/explanation/architecture-globale.md:1
msgid "Architecture globale"
msgstr ""

#: src/SUMMARY.md:68
#: src/administration_manual/explanation/modele-deploiement.md:1
msgid "Modèle de déploiement"
msgstr ""

#: src/SUMMARY.md:69 src/SUMMARY.md:107
#: src/administration_manual/explanation/ci-dagger.md:1
#: src/developer_manual/explanation/ci-dagger-easy-vs-power.md:1
msgid "CI Dagger : Easy Mode vs Power Mode"
msgstr ""

#: src/SUMMARY.md:70
#: src/administration_manual/explanation/strategie-sauvegarde.md:1
msgid "Stratégie de sauvegarde"
msgstr ""

#: src/SUMMARY.md:74 src/developer_manual/index.md:1
msgid "Manuel développeur"
msgstr ""

#: src/SUMMARY.md:78
msgid "01 — Démarrer avec le code gitrust"
msgstr ""

#: src/SUMMARY.md:79
#: src/developer_manual/tutorials/02-premiere-contribution.md:1
msgid "02 — Première contribution"
msgstr ""

#: src/SUMMARY.md:80
#: src/developer_manual/tutorials/03-creer-un-worker-async.md:1
msgid "03 — Créer un worker async (capstone)"
msgstr ""

#: src/SUMMARY.md:82 src/developer_manual/how-to/contribuer-workflow-pr.md:1
msgid "Workflow de contribution et PR"
msgstr ""

#: src/SUMMARY.md:83 src/developer_manual/how-to/lancer-tests-unitaires.md:1
msgid "Lancer les tests unitaires"
msgstr ""

#: src/SUMMARY.md:84
msgid "Lancer les tests E2E"
msgstr ""

#: src/SUMMARY.md:85 src/developer_manual/how-to/ajouter-route-web.md:1
msgid "Ajouter une route web"
msgstr ""

#: src/SUMMARY.md:86 src/developer_manual/how-to/ajouter-service-metier.md:1
msgid "Ajouter un service métier"
msgstr ""

#: src/SUMMARY.md:87 src/developer_manual/how-to/ajouter-migration-db.md:1
msgid "Ajouter une migration de base de données"
msgstr ""

#: src/SUMMARY.md:88 src/developer_manual/how-to/implementer-webhooks.md:1
msgid "Implémenter des webhooks"
msgstr ""

#: src/SUMMARY.md:89 src/developer_manual/how-to/implementer-endpoint-api.md:1
msgid "Implémenter un endpoint API"
msgstr ""

#: src/SUMMARY.md:90
msgid "Importer un dépôt externe (code)"
msgstr ""

#: src/SUMMARY.md:91
msgid "Contribuer à rustwarden upstream"
msgstr ""

#: src/SUMMARY.md:92 src/developer_manual/how-to/passer-la-qa-avant-merge.md:1
msgid "Passer la QA avant un merge"
msgstr ""

#: src/SUMMARY.md:94
msgid "Architecture des crates"
msgstr ""

#: src/SUMMARY.md:95 src/developer_manual/reference/services-api-interne.md:1
msgid "Services et API interne"
msgstr ""

#: src/SUMMARY.md:97
msgid "Règles QA et conformité ANSSI"
msgstr ""

#: src/SUMMARY.md:99 src/developer_manual/reference/git-hooks-post-receive.md:1
msgid "Hooks Git post-receive"
msgstr ""

#: src/SUMMARY.md:100 src/developer_manual/reference/rustwarden-core-api.md:1
msgid "API rustwarden-core"
msgstr ""

#: src/SUMMARY.md:102
#: src/developer_manual/explanation/vue-ensemble-architecture.md:1
msgid "Vue d'ensemble de l'architecture"
msgstr ""

#: src/SUMMARY.md:103 src/developer_manual/explanation/flux-requetes.md:1
msgid "Flux de requêtes"
msgstr ""

#: src/SUMMARY.md:104
#: src/developer_manual/explanation/modele-permissions-rbac.md:1
msgid "Modèle de permissions RBAC"
msgstr ""

#: src/SUMMARY.md:105 src/developer_manual/explanation/2fa-fonctionnement.md:1
msgid "Fonctionnement du 2FA"
msgstr ""

#: src/SUMMARY.md:106 src/developer_manual/explanation/hierarchie-labels.md:1
msgid "Hiérarchie des labels"
msgstr ""

#: src/SUMMARY.md:108 src/developer_manual/explanation/decisions-ui-htmx.md:1
msgid "Décisions UI (HTMX, DaisyUI)"
msgstr ""

#: src/SUMMARY.md:109 src/developer_manual/explanation/patron-worker-async.md:1
msgid "Patron worker async"
msgstr ""

#: src/SUMMARY.md:113
msgid "Bibliothèque de templates"
msgstr ""

#: src/SUMMARY.md:115
msgid "Catalogue des templates"
msgstr ""

#: src/introduction.md:3
msgid "Qu'est-ce que gitrust ?"
msgstr ""

#: src/introduction.md:5
msgid ""
"**gitrust** est une forge Git self-hosted écrite en Rust, conçue pour les "
"équipes de 3 à 20 personnes qui souhaitent maîtriser leur infrastructure de "
"développement. Elle offre un serveur HTTP (`:4000`) et SSH (`:2222`), une CI "
"intégrée via Dagger, la génération de SBOM avec Syft et l'intégration "
"Dependency-Track, une gestion fine des permissions (4 rôles), la double "
"authentification, des labels hiérarchiques et une conformité ANSSI PA-074."
msgstr ""

#: src/introduction.md:7
msgid ""
"Une instance publique de démonstration est accessible sur [demo.gitrust.eu]"
"(https://demo.gitrust.eu)."
msgstr ""

#: src/introduction.md:9
msgid "À qui s'adresse cette documentation ?"
msgstr ""

#: src/introduction.md:11
msgid ""
"Cette documentation est organisée en quatre parties selon leurs publics "
"respectifs :"
msgstr ""

#: src/introduction.md:13
msgid ""
"**Manuel utilisateur** — pour les développeurs qui _utilisent_ une instance "
"gitrust existante : push/pull, pull requests, issues, CI, notifications. "
"Prérequis : savoir utiliser Git en ligne de commande."
msgstr ""

#: src/introduction.md:14
msgid ""
"**Manuel d'administration** — pour les ops et self-hosters qui déploient, "
"configurent et maintiennent une instance en production. Prérequis : "
"administration Linux, notions de réseau et TLS."
msgstr ""

#: src/introduction.md:15
msgid ""
"**Manuel développeur** — pour les contributeurs au code gitrust et les "
"développeurs qui construisent des intégrations sur l'API publique. "
"Prérequis : Rust (pour contribuer) ou un langage client (pour l'API)."
msgstr ""

#: src/introduction.md:16
msgid ""
"**Bibliothèque de templates** — pour tous les profils, lorsqu'ils cherchent "
"un point de départ prêt à l'emploi (fichiers `.env`, `docker-compose.yml`, "
"configs reverse-proxy, scripts de backup, exemples de clients API)."
msgstr ""

#: src/introduction.md:18
msgid "Comment cette documentation est-elle structurée ?"
msgstr ""

#: src/introduction.md:20
msgid ""
"Cette documentation suit le cadre **Diátaxis**, qui distingue quatre types "
"de contenu selon le besoin du lecteur :"
msgstr ""

#: src/introduction.md:22
msgid "Type"
msgstr ""

#: src/introduction.md:22
msgid "Quand l'utiliser"
msgstr ""

#: src/introduction.md:22 src/developer_manual/reference/regles-qa-anssi.md:61
#: src/developer_manual/reference/regles-qa-anssi.md:74
msgid "Exemples"
msgstr ""

#: src/introduction.md:24
msgid "**Tutoriels**"
msgstr ""

#: src/introduction.md:24
msgid "Quand vous apprenez"
msgstr ""

#: src/introduction.md:24
msgid "Installer gitrust, créer votre premier dépôt"
msgstr ""

#: src/introduction.md:25
msgid "**Guides pratiques**"
msgstr ""

#: src/introduction.md:25
msgid "Quand vous résolvez un problème précis"
msgstr ""

#: src/introduction.md:25
msgid "Configurer SMTP, gérer les clés SSH"
msgstr ""

#: src/introduction.md:26
msgid "**Référence**"
msgstr ""

#: src/introduction.md:26
msgid "Quand vous cherchez une information technique"
msgstr ""

#: src/introduction.md:26
msgid "Variables d'environnement, schéma API REST"
msgstr ""

#: src/introduction.md:27
msgid "**Explication**"
msgstr ""

#: src/introduction.md:27
msgid "Quand vous voulez comprendre le pourquoi"
msgstr ""

#: src/introduction.md:27
msgid "Architecture des crates, modèle RBAC"
msgstr ""

#: src/introduction.md:29
msgid ""
"Chaque manuel (utilisateur, administration, développeur) contient ces quatre "
"types de contenu organisés de manière indépendante."
msgstr ""

#: src/introduction.md:31
msgid "Naviguer dans la documentation"
msgstr ""

#: src/introduction.md:33
msgid ""
"[Manuel utilisateur](user_manual/index.md) — collaborer sur gitrust en tant "
"que développeur"
msgstr ""

#: src/introduction.md:34
msgid ""
"[Manuel d'administration](administration_manual/index.md) — déployer et "
"exploiter une instance"
msgstr ""

#: src/introduction.md:35
msgid ""
"[Manuel développeur](developer_manual/index.md) — contribuer au code ou "
"consommer l'API"
msgstr ""

#: src/introduction.md:36
msgid ""
"[Bibliothèque de templates](template/index.md) — configs et scripts copiables"
msgstr ""

#: src/user_manual/index.md:3
msgid ""
"Ce manuel t'accompagne depuis ta première connexion à une instance gitrust "
"jusqu'à l'autonomie complète : pousser du code, collaborer via les pull "
"requests, gérer les issues et automatiser tes workflows avec la CI intégrée. "
"Tu n'as pas besoin d'administrer ni de comprendre l'architecture interne — "
"ce manuel suppose seulement que tu sais utiliser Git en ligne de commande."
msgstr ""

#: src/user_manual/index.md:5 src/administration_manual/index.md:5
msgid "Parcours d'apprentissage"
msgstr ""

#: src/user_manual/index.md:7
msgid ""
"Le manuel est structuré comme un **parcours progressif** de 4 tutoriels. "
"Chaque tutoriel te laisse dans un état stable, vérifié, avant de passer au "
"suivant. L'aide fournie recule d'un cran à chaque étape (du copier-coller "
"intégral vers la composition autonome)."
msgstr ""

#: src/user_manual/index.md:18
msgid ""
"**Checkpoint de parcours** : avant de passer au tutoriel 02, tu dois pouvoir "
"te connecter à gitrust, voir ton dépôt dans l'interface et l'accès SSH "
"configuré. Si ce n'est pas le cas, relis le tutoriel 01."
msgstr ""

#: src/user_manual/index.md:20
msgid ""
"**Checkpoint de parcours** : avant le tutoriel 03, tu dois avoir poussé au "
"moins un commit sur ta branche via SSH. Si ce n'est pas le cas, relis le "
"tutoriel 02."
msgstr ""

#: src/user_manual/index.md:22
msgid ""
"**Checkpoint de parcours** : avant le tutoriel 04, tu dois avoir ouvert et "
"mergé une pull request. Si ce n'est pas le cas, relis le tutoriel 03."
msgstr ""

#: src/user_manual/index.md:26 src/administration_manual/index.md:24
#: src/developer_manual/index.md:23
msgid "Tutoriels — apprendre en faisant"
msgstr ""

#: src/user_manual/index.md:28
msgid ""
"Les tutoriels sont guidés pas-à-pas avec des sorties verbatim attendues. "
"Suis-les dans l'ordre — chacun suppose le précédent complété."
msgstr ""

#: src/user_manual/index.md:30
msgid ""
"[01 — Premiers pas : 2FA, clé SSH, premier dépôt](tutorials/01-premier-pas."
"md) — ~20 min"
msgstr ""

#: src/user_manual/index.md:31
msgid ""
"[02 — Cloner et pousser du code](tutorials/02-cloner-pousser.md) — ~25 min"
msgstr ""

#: src/user_manual/index.md:32
msgid ""
"[03 — Collaborer : équipes, issues, pull requests](tutorials/03-collaborer."
"md) — ~25 min"
msgstr ""

#: src/user_manual/index.md:33
msgid "[04 — Automatiser avec la CI](tutorials/04-automatiser-ci.md) — ~20 min"
msgstr ""

#: src/user_manual/index.md:37 src/administration_manual/index.md:35
#: src/developer_manual/index.md:33
msgid "How-to — recettes pour les tâches courantes"
msgstr ""

#: src/user_manual/index.md:39
msgid ""
"Les how-to répondent à « comment faire X » sans explication de fond. Tu peux "
"les consulter dans n'importe quel ordre selon ton besoin immédiat."
msgstr ""

#: src/user_manual/index.md:41
msgid ""
"Ces guides supposent que tu as suivi le parcours tutoriels. Ils ne répètent "
"pas les étapes de base."
msgstr ""

#: src/user_manual/index.md:43
msgid "[Gérer ses clés SSH](how-to/gerer-cles-ssh.md)"
msgstr ""

#: src/user_manual/index.md:44
msgid "[Configurer la 2FA](how-to/configurer-2fa.md)"
msgstr ""

#: src/user_manual/index.md:45
msgid "[Créer un Personal Access Token](how-to/creer-personal-access-token.md)"
msgstr ""

#: src/user_manual/index.md:46
msgid "[Gérer les équipes et permissions](how-to/gerer-equipes-permissions.md)"
msgstr ""

#: src/user_manual/index.md:47
msgid "[Ouvrir une pull request](how-to/ouvrir-pull-request.md)"
msgstr ""

#: src/user_manual/index.md:48
msgid ""
"[Fusionner : fast-forward, squash, merge commit](how-to/fusionner-strategies."
"md)"
msgstr ""

#: src/user_manual/index.md:49
msgid "[Utiliser les labels hiérarchiques](how-to/utiliser-labels-issues.md)"
msgstr ""

#: src/user_manual/index.md:50
msgid "[Importer un dépôt externe](how-to/importer-depot-externe.md)"
msgstr ""

#: src/user_manual/index.md:51
msgid "[Consulter le SBOM de ton projet](how-to/consulter-sbom.md)"
msgstr ""

#: src/user_manual/index.md:55 src/administration_manual/index.md:55
#: src/developer_manual/index.md:51
msgid "Référence — informations techniques exactes"
msgstr ""

#: src/user_manual/index.md:57
msgid ""
"La référence est destinée à la consultation ponctuelle, pas à la lecture "
"linéaire. Elle documente les formats, schémas et comportements exacts."
msgstr ""

#: src/user_manual/index.md:59
msgid "[Modèle de permissions (4 rôles)](reference/modele-permissions.md)"
msgstr ""

#: src/user_manual/index.md:60
msgid ""
"[API REST v1 — authentification, pagination, codes d'erreur](reference/api-"
"rest-v1.md)"
msgstr ""

#: src/user_manual/index.md:61
msgid ""
"[Schéma YAML `.gitrust-ci.yml` (Easy Mode)](reference/gitrust-ci-yml-schema."
"md)"
msgstr ""

#: src/user_manual/index.md:62
msgid "[Syntaxe Markdown supportée](reference/markdown-et-syntaxe.md)"
msgstr ""

#: src/user_manual/index.md:63
msgid "[Notifications : SSE, e-mail, préférences](reference/notifications.md)"
msgstr ""

#: src/user_manual/index.md:67 src/administration_manual/index.md:67
#: src/developer_manual/index.md:65
msgid "Explication — comprendre le pourquoi"
msgstr ""

#: src/user_manual/index.md:69
msgid ""
"Les explanations t'aident à construire des modèles mentaux durables. Lis-les "
"quand tu veux comprendre _pourquoi_ gitrust fonctionne ainsi, pas seulement "
"_comment_."
msgstr ""

#: src/user_manual/index.md:71
msgid "[Modèle de collaboration gitrust](explanation/modele-collaboration.md)"
msgstr ""

#: src/user_manual/index.md:72
msgid ""
"[Sécurité utilisateur : 2FA, PAT, audit log](explanation/securite-"
"utilisateur.md)"
msgstr ""

#: src/user_manual/index.md:73
msgid ""
"[Cycle de vie d'une pull request](explanation/cycle-vie-pull-request.md)"
msgstr ""

#: src/user_manual/tutorials/index.md:3
#: src/user_manual/tutorials/02-cloner-pousser.md:3
#: src/user_manual/tutorials/03-collaborer.md:3
#: src/user_manual/tutorials/04-automatiser-ci.md:3
#: src/user_manual/how-to/index.md:3 src/user_manual/how-to/gerer-cles-ssh.md:3
#: src/user_manual/how-to/configurer-2fa.md:3
#: src/user_manual/how-to/creer-personal-access-token.md:3
#: src/user_manual/how-to/gerer-equipes-permissions.md:3
#: src/user_manual/how-to/ouvrir-pull-request.md:3
#: src/user_manual/how-to/fusionner-strategies.md:3
#: src/user_manual/how-to/utiliser-labels-issues.md:3
#: src/user_manual/how-to/importer-depot-externe.md:3
#: src/user_manual/how-to/consulter-sbom.md:3
#: src/user_manual/reference/index.md:3
#: src/user_manual/reference/modele-permissions.md:3
#: src/user_manual/reference/api-rest-v1.md:3
#: src/user_manual/reference/gitrust-ci-yml-schema.md:3
#: src/user_manual/reference/markdown-et-syntaxe.md:3
#: src/user_manual/reference/notifications.md:3
#: src/user_manual/explanation/index.md:3
#: src/user_manual/explanation/modele-collaboration.md:3
#: src/user_manual/explanation/securite-utilisateur.md:3
#: src/user_manual/explanation/cycle-vie-pull-request.md:3
#: src/administration_manual/tutorials/index.md:3
#: src/administration_manual/tutorials/02-installation-systemd.md:3
#: src/administration_manual/tutorials/03-premier-demarrage.md:3
#: src/administration_manual/how-to/index.md:3
#: src/administration_manual/how-to/sauvegarder-restaurer.md:3
#: src/administration_manual/how-to/mettre-a-jour.md:3
#: src/administration_manual/how-to/configurer-smtp.md:3
#: src/administration_manual/how-to/configurer-oauth.md:3
#: src/administration_manual/how-to/tuner-rate-limiting.md:3
#: src/administration_manual/how-to/forcer-2fa-globalement.md:3
#: src/administration_manual/how-to/depanner-ssh.md:3
#: src/administration_manual/how-to/depanner-ci.md:3
#: src/administration_manual/how-to/gerer-utilisateurs-admin.md:3
#: src/administration_manual/how-to/auditer-instance.md:3
#: src/administration_manual/reference/index.md:3
#: src/administration_manual/reference/variables-environnement.md:3
#: src/administration_manual/reference/schema-base-de-donnees.md:3
#: src/administration_manual/reference/ports-et-services.md:3
#: src/administration_manual/reference/conformite-anssi-pa074.md:3
#: src/administration_manual/explanation/index.md:3
#: src/administration_manual/explanation/architecture-globale.md:3
#: src/administration_manual/explanation/modele-deploiement.md:3
#: src/administration_manual/explanation/ci-dagger.md:3
#: src/administration_manual/explanation/strategie-sauvegarde.md:3
#: src/developer_manual/tutorials/index.md:3
#: src/developer_manual/tutorials/02-premiere-contribution.md:3
#: src/developer_manual/tutorials/03-creer-un-worker-async.md:3
#: src/developer_manual/how-to/index.md:3
#: src/developer_manual/how-to/contribuer-workflow-pr.md:3
#: src/developer_manual/how-to/ajouter-route-web.md:3
#: src/developer_manual/how-to/ajouter-service-metier.md:3
#: src/developer_manual/how-to/ajouter-migration-db.md:3
#: src/developer_manual/how-to/implementer-webhooks.md:3
#: src/developer_manual/how-to/implementer-endpoint-api.md:3
#: src/developer_manual/how-to/passer-la-qa-avant-merge.md:3
#: src/developer_manual/reference/index.md:3
#: src/developer_manual/reference/services-api-interne.md:3
#: src/developer_manual/reference/schema-base-donnees.md:3
#: src/developer_manual/reference/api-rest-v1.md:3
#: src/developer_manual/reference/git-hooks-post-receive.md:3
#: src/developer_manual/reference/rustwarden-core-api.md:3
#: src/developer_manual/explanation/index.md:3
#: src/developer_manual/explanation/modele-permissions-rbac.md:3
#: src/developer_manual/explanation/2fa-fonctionnement.md:3
#: src/developer_manual/explanation/hierarchie-labels.md:3
#: src/developer_manual/explanation/ci-dagger-easy-vs-power.md:3
#: src/developer_manual/explanation/decisions-ui-htmx.md:3
#: src/developer_manual/explanation/patron-worker-async.md:3
msgid ""
"**Page à rédiger.** Ce contenu est un stub généré automatiquement lors du "
"scaffolding initial."
msgstr ""

#: src/user_manual/tutorials/index.md:5
#: src/user_manual/tutorials/02-cloner-pousser.md:5
#: src/user_manual/tutorials/03-collaborer.md:5
#: src/user_manual/tutorials/04-automatiser-ci.md:5
#: src/user_manual/how-to/index.md:5 src/user_manual/how-to/gerer-cles-ssh.md:5
#: src/user_manual/how-to/configurer-2fa.md:5
#: src/user_manual/how-to/creer-personal-access-token.md:5
#: src/user_manual/how-to/gerer-equipes-permissions.md:5
#: src/user_manual/how-to/ouvrir-pull-request.md:5
#: src/user_manual/how-to/fusionner-strategies.md:5
#: src/user_manual/how-to/utiliser-labels-issues.md:5
#: src/user_manual/how-to/importer-depot-externe.md:5
#: src/user_manual/how-to/consulter-sbom.md:5
#: src/user_manual/reference/index.md:5
#: src/user_manual/reference/modele-permissions.md:5
#: src/user_manual/reference/api-rest-v1.md:5
#: src/user_manual/reference/gitrust-ci-yml-schema.md:5
#: src/user_manual/reference/markdown-et-syntaxe.md:5
#: src/user_manual/reference/notifications.md:5
#: src/user_manual/explanation/index.md:5
#: src/user_manual/explanation/modele-collaboration.md:5
#: src/user_manual/explanation/securite-utilisateur.md:5
#: src/user_manual/explanation/cycle-vie-pull-request.md:5
#: src/administration_manual/tutorials/index.md:5
#: src/administration_manual/tutorials/02-installation-systemd.md:5
#: src/administration_manual/tutorials/03-premier-demarrage.md:5
#: src/administration_manual/how-to/index.md:5
#: src/administration_manual/how-to/sauvegarder-restaurer.md:5
#: src/administration_manual/how-to/mettre-a-jour.md:5
#: src/administration_manual/how-to/configurer-smtp.md:5
#: src/administration_manual/how-to/configurer-oauth.md:5
#: src/administration_manual/how-to/tuner-rate-limiting.md:5
#: src/administration_manual/how-to/forcer-2fa-globalement.md:5
#: src/administration_manual/how-to/depanner-ssh.md:5
#: src/administration_manual/how-to/depanner-ci.md:5
#: src/administration_manual/how-to/gerer-utilisateurs-admin.md:5
#: src/administration_manual/how-to/auditer-instance.md:5
#: src/administration_manual/reference/index.md:5
#: src/administration_manual/reference/variables-environnement.md:5
#: src/administration_manual/reference/schema-base-de-donnees.md:5
#: src/administration_manual/reference/ports-et-services.md:5
#: src/administration_manual/reference/conformite-anssi-pa074.md:5
#: src/administration_manual/explanation/index.md:5
#: src/administration_manual/explanation/architecture-globale.md:5
#: src/administration_manual/explanation/modele-deploiement.md:5
#: src/administration_manual/explanation/ci-dagger.md:5
#: src/administration_manual/explanation/strategie-sauvegarde.md:5
#: src/developer_manual/tutorials/index.md:5
#: src/developer_manual/tutorials/02-premiere-contribution.md:5
#: src/developer_manual/tutorials/03-creer-un-worker-async.md:5
#: src/developer_manual/how-to/index.md:5
#: src/developer_manual/how-to/contribuer-workflow-pr.md:5
#: src/developer_manual/how-to/ajouter-route-web.md:5
#: src/developer_manual/how-to/ajouter-service-metier.md:5
#: src/developer_manual/how-to/ajouter-migration-db.md:5
#: src/developer_manual/how-to/implementer-webhooks.md:5
#: src/developer_manual/how-to/implementer-endpoint-api.md:5
#: src/developer_manual/how-to/passer-la-qa-avant-merge.md:5
#: src/developer_manual/reference/index.md:5
#: src/developer_manual/reference/services-api-interne.md:5
#: src/developer_manual/reference/schema-base-donnees.md:5
#: src/developer_manual/reference/api-rest-v1.md:5
#: src/developer_manual/reference/git-hooks-post-receive.md:5
#: src/developer_manual/reference/rustwarden-core-api.md:5
#: src/developer_manual/explanation/index.md:5
#: src/developer_manual/explanation/modele-permissions-rbac.md:5
#: src/developer_manual/explanation/2fa-fonctionnement.md:5
#: src/developer_manual/explanation/hierarchie-labels.md:5
#: src/developer_manual/explanation/ci-dagger-easy-vs-power.md:5
#: src/developer_manual/explanation/decisions-ui-htmx.md:5
#: src/developer_manual/explanation/patron-worker-async.md:5
msgid ""
"Consultez [`.plans/001-scaffold-initial.md`](../../.plans/001-scaffold-"
"initial.md) pour le contexte et la place de cette page dans le parcours."
msgstr ""

#: src/user_manual/tutorials/index.md:7
#: src/user_manual/tutorials/02-cloner-pousser.md:7
#: src/user_manual/tutorials/03-collaborer.md:7
#: src/user_manual/tutorials/04-automatiser-ci.md:7
#: src/user_manual/how-to/index.md:7 src/user_manual/how-to/gerer-cles-ssh.md:7
#: src/user_manual/how-to/configurer-2fa.md:7
#: src/user_manual/how-to/creer-personal-access-token.md:7
#: src/user_manual/how-to/gerer-equipes-permissions.md:7
#: src/user_manual/how-to/ouvrir-pull-request.md:7
#: src/user_manual/how-to/fusionner-strategies.md:7
#: src/user_manual/how-to/utiliser-labels-issues.md:7
#: src/user_manual/how-to/importer-depot-externe.md:7
#: src/user_manual/how-to/consulter-sbom.md:7
#: src/user_manual/reference/index.md:7
#: src/user_manual/reference/modele-permissions.md:7
#: src/user_manual/reference/api-rest-v1.md:7
#: src/user_manual/reference/gitrust-ci-yml-schema.md:7
#: src/user_manual/reference/markdown-et-syntaxe.md:7
#: src/user_manual/reference/notifications.md:7
#: src/user_manual/explanation/index.md:7
#: src/user_manual/explanation/modele-collaboration.md:7
#: src/user_manual/explanation/securite-utilisateur.md:7
#: src/user_manual/explanation/cycle-vie-pull-request.md:7
#: src/administration_manual/tutorials/index.md:7
#: src/administration_manual/tutorials/02-installation-systemd.md:7
#: src/administration_manual/tutorials/03-premier-demarrage.md:7
#: src/administration_manual/how-to/index.md:7
#: src/administration_manual/how-to/sauvegarder-restaurer.md:7
#: src/administration_manual/how-to/mettre-a-jour.md:7
#: src/administration_manual/how-to/configurer-smtp.md:7
#: src/administration_manual/how-to/configurer-oauth.md:7
#: src/administration_manual/how-to/tuner-rate-limiting.md:7
#: src/administration_manual/how-to/forcer-2fa-globalement.md:7
#: src/administration_manual/how-to/depanner-ssh.md:7
#: src/administration_manual/how-to/depanner-ci.md:7
#: src/administration_manual/how-to/gerer-utilisateurs-admin.md:7
#: src/administration_manual/how-to/auditer-instance.md:7
#: src/administration_manual/reference/index.md:7
#: src/administration_manual/reference/variables-environnement.md:7
#: src/administration_manual/reference/schema-base-de-donnees.md:7
#: src/administration_manual/reference/ports-et-services.md:7
#: src/administration_manual/reference/conformite-anssi-pa074.md:7
#: src/administration_manual/explanation/index.md:7
#: src/administration_manual/explanation/architecture-globale.md:7
#: src/administration_manual/explanation/modele-deploiement.md:7
#: src/administration_manual/explanation/ci-dagger.md:7
#: src/administration_manual/explanation/strategie-sauvegarde.md:7
#: src/developer_manual/tutorials/index.md:7
#: src/developer_manual/tutorials/02-premiere-contribution.md:7
#: src/developer_manual/tutorials/03-creer-un-worker-async.md:7
#: src/developer_manual/how-to/index.md:7
#: src/developer_manual/how-to/contribuer-workflow-pr.md:7
#: src/developer_manual/how-to/ajouter-route-web.md:7
#: src/developer_manual/how-to/ajouter-service-metier.md:7
#: src/developer_manual/how-to/ajouter-migration-db.md:7
#: src/developer_manual/how-to/implementer-webhooks.md:7
#: src/developer_manual/how-to/implementer-endpoint-api.md:7
#: src/developer_manual/how-to/passer-la-qa-avant-merge.md:7
#: src/developer_manual/reference/index.md:7
#: src/developer_manual/reference/services-api-interne.md:7
#: src/developer_manual/reference/schema-base-donnees.md:7
#: src/developer_manual/reference/api-rest-v1.md:7
#: src/developer_manual/reference/git-hooks-post-receive.md:7
#: src/developer_manual/reference/rustwarden-core-api.md:7
#: src/developer_manual/explanation/index.md:7
#: src/developer_manual/explanation/modele-permissions-rbac.md:7
#: src/developer_manual/explanation/2fa-fonctionnement.md:7
#: src/developer_manual/explanation/hierarchie-labels.md:7
#: src/developer_manual/explanation/ci-dagger-easy-vs-power.md:7
#: src/developer_manual/explanation/decisions-ui-htmx.md:7
#: src/developer_manual/explanation/patron-worker-async.md:7
msgid "TODO"
msgstr ""

#: src/user_manual/tutorials/index.md:9
#: src/user_manual/tutorials/02-cloner-pousser.md:9
#: src/user_manual/tutorials/03-collaborer.md:9
#: src/user_manual/tutorials/04-automatiser-ci.md:9
#: src/user_manual/how-to/index.md:9 src/user_manual/how-to/gerer-cles-ssh.md:9
#: src/user_manual/how-to/configurer-2fa.md:9
#: src/user_manual/how-to/creer-personal-access-token.md:9
#: src/user_manual/how-to/gerer-equipes-permissions.md:9
#: src/user_manual/how-to/ouvrir-pull-request.md:9
#: src/user_manual/how-to/fusionner-strategies.md:9
#: src/user_manual/how-to/utiliser-labels-issues.md:9
#: src/user_manual/how-to/importer-depot-externe.md:9
#: src/user_manual/how-to/consulter-sbom.md:9
#: src/user_manual/reference/index.md:9
#: src/user_manual/reference/modele-permissions.md:9
#: src/user_manual/reference/api-rest-v1.md:9
#: src/user_manual/reference/gitrust-ci-yml-schema.md:9
#: src/user_manual/reference/markdown-et-syntaxe.md:9
#: src/user_manual/reference/notifications.md:9
#: src/user_manual/explanation/index.md:9
#: src/user_manual/explanation/modele-collaboration.md:9
#: src/user_manual/explanation/securite-utilisateur.md:9
#: src/user_manual/explanation/cycle-vie-pull-request.md:9
#: src/administration_manual/tutorials/index.md:9
#: src/administration_manual/tutorials/02-installation-systemd.md:9
#: src/administration_manual/tutorials/03-premier-demarrage.md:9
#: src/administration_manual/how-to/index.md:9
#: src/administration_manual/how-to/sauvegarder-restaurer.md:9
#: src/administration_manual/how-to/mettre-a-jour.md:9
#: src/administration_manual/how-to/configurer-smtp.md:9
#: src/administration_manual/how-to/configurer-oauth.md:9
#: src/administration_manual/how-to/tuner-rate-limiting.md:9
#: src/administration_manual/how-to/forcer-2fa-globalement.md:9
#: src/administration_manual/how-to/depanner-ssh.md:9
#: src/administration_manual/how-to/depanner-ci.md:9
#: src/administration_manual/how-to/gerer-utilisateurs-admin.md:9
#: src/administration_manual/how-to/auditer-instance.md:9
#: src/administration_manual/reference/index.md:9
#: src/administration_manual/reference/variables-environnement.md:9
#: src/administration_manual/reference/schema-base-de-donnees.md:9
#: src/administration_manual/reference/ports-et-services.md:9
#: src/administration_manual/reference/conformite-anssi-pa074.md:9
#: src/administration_manual/explanation/index.md:9
#: src/administration_manual/explanation/architecture-globale.md:9
#: src/administration_manual/explanation/modele-deploiement.md:9
#: src/administration_manual/explanation/ci-dagger.md:9
#: src/administration_manual/explanation/strategie-sauvegarde.md:9
#: src/developer_manual/tutorials/index.md:9
#: src/developer_manual/tutorials/02-premiere-contribution.md:9
#: src/developer_manual/tutorials/03-creer-un-worker-async.md:9
#: src/developer_manual/how-to/index.md:9
#: src/developer_manual/how-to/contribuer-workflow-pr.md:9
#: src/developer_manual/how-to/ajouter-route-web.md:9
#: src/developer_manual/how-to/ajouter-service-metier.md:9
#: src/developer_manual/how-to/ajouter-migration-db.md:9
#: src/developer_manual/how-to/implementer-webhooks.md:9
#: src/developer_manual/how-to/implementer-endpoint-api.md:9
#: src/developer_manual/how-to/passer-la-qa-avant-merge.md:9
#: src/developer_manual/reference/index.md:9
#: src/developer_manual/reference/services-api-interne.md:9
#: src/developer_manual/reference/schema-base-donnees.md:9
#: src/developer_manual/reference/api-rest-v1.md:9
#: src/developer_manual/reference/git-hooks-post-receive.md:9
#: src/developer_manual/reference/rustwarden-core-api.md:9
#: src/developer_manual/explanation/index.md:9
#: src/developer_manual/explanation/modele-permissions-rbac.md:9
#: src/developer_manual/explanation/2fa-fonctionnement.md:9
#: src/developer_manual/explanation/hierarchie-labels.md:9
#: src/developer_manual/explanation/ci-dagger-easy-vs-power.md:9
#: src/developer_manual/explanation/decisions-ui-htmx.md:9
#: src/developer_manual/explanation/patron-worker-async.md:9
msgid ""
"Rédiger cette page selon son mode Diátaxis (voir [CLAUDE.md](../../CLAUDE."
"md))"
msgstr ""

#: src/user_manual/tutorials/index.md:10
#: src/user_manual/tutorials/02-cloner-pousser.md:10
#: src/user_manual/tutorials/03-collaborer.md:10
#: src/user_manual/tutorials/04-automatiser-ci.md:10
#: src/user_manual/how-to/index.md:10
#: src/user_manual/how-to/gerer-cles-ssh.md:10
#: src/user_manual/how-to/configurer-2fa.md:10
#: src/user_manual/how-to/creer-personal-access-token.md:10
#: src/user_manual/how-to/gerer-equipes-permissions.md:10
#: src/user_manual/how-to/ouvrir-pull-request.md:10
#: src/user_manual/how-to/fusionner-strategies.md:10
#: src/user_manual/how-to/utiliser-labels-issues.md:10
#: src/user_manual/how-to/importer-depot-externe.md:10
#: src/user_manual/how-to/consulter-sbom.md:10
#: src/user_manual/reference/index.md:10
#: src/user_manual/reference/modele-permissions.md:10
#: src/user_manual/reference/api-rest-v1.md:10
#: src/user_manual/reference/gitrust-ci-yml-schema.md:10
#: src/user_manual/reference/markdown-et-syntaxe.md:10
#: src/user_manual/reference/notifications.md:10
#: src/user_manual/explanation/index.md:10
#: src/user_manual/explanation/modele-collaboration.md:10
#: src/user_manual/explanation/securite-utilisateur.md:10
#: src/user_manual/explanation/cycle-vie-pull-request.md:10
#: src/administration_manual/tutorials/index.md:10
#: src/administration_manual/tutorials/02-installation-systemd.md:10
#: src/administration_manual/tutorials/03-premier-demarrage.md:10
#: src/administration_manual/how-to/index.md:10
#: src/administration_manual/how-to/sauvegarder-restaurer.md:10
#: src/administration_manual/how-to/mettre-a-jour.md:10
#: src/administration_manual/how-to/configurer-smtp.md:10
#: src/administration_manual/how-to/configurer-oauth.md:10
#: src/administration_manual/how-to/tuner-rate-limiting.md:10
#: src/administration_manual/how-to/forcer-2fa-globalement.md:10
#: src/administration_manual/how-to/depanner-ssh.md:10
#: src/administration_manual/how-to/depanner-ci.md:10
#: src/administration_manual/how-to/gerer-utilisateurs-admin.md:10
#: src/administration_manual/how-to/auditer-instance.md:10
#: src/administration_manual/reference/index.md:10
#: src/administration_manual/reference/variables-environnement.md:10
#: src/administration_manual/reference/schema-base-de-donnees.md:10
#: src/administration_manual/reference/ports-et-services.md:10
#: src/administration_manual/reference/conformite-anssi-pa074.md:10
#: src/administration_manual/explanation/index.md:10
#: src/administration_manual/explanation/architecture-globale.md:10
#: src/administration_manual/explanation/modele-deploiement.md:10
#: src/administration_manual/explanation/ci-dagger.md:10
#: src/administration_manual/explanation/strategie-sauvegarde.md:10
#: src/developer_manual/tutorials/index.md:10
#: src/developer_manual/tutorials/02-premiere-contribution.md:10
#: src/developer_manual/tutorials/03-creer-un-worker-async.md:10
#: src/developer_manual/how-to/index.md:10
#: src/developer_manual/how-to/contribuer-workflow-pr.md:10
#: src/developer_manual/how-to/ajouter-route-web.md:10
#: src/developer_manual/how-to/ajouter-service-metier.md:10
#: src/developer_manual/how-to/ajouter-migration-db.md:10
#: src/developer_manual/how-to/implementer-webhooks.md:10
#: src/developer_manual/how-to/implementer-endpoint-api.md:10
#: src/developer_manual/how-to/passer-la-qa-avant-merge.md:10
#: src/developer_manual/reference/index.md:10
#: src/developer_manual/reference/services-api-interne.md:10
#: src/developer_manual/reference/schema-base-donnees.md:10
#: src/developer_manual/reference/api-rest-v1.md:10
#: src/developer_manual/reference/git-hooks-post-receive.md:10
#: src/developer_manual/reference/rustwarden-core-api.md:10
#: src/developer_manual/explanation/index.md:10
#: src/developer_manual/explanation/modele-permissions-rbac.md:10
#: src/developer_manual/explanation/2fa-fonctionnement.md:10
#: src/developer_manual/explanation/hierarchie-labels.md:10
#: src/developer_manual/explanation/ci-dagger-easy-vs-power.md:10
#: src/developer_manual/explanation/decisions-ui-htmx.md:10
#: src/developer_manual/explanation/patron-worker-async.md:10
msgid ""
"Appliquer le template pédagogique si c'est un tutoriel ou une explanation "
"(voir skill `pedagogie`)"
msgstr ""

#: src/user_manual/tutorials/index.md:11
#: src/user_manual/tutorials/02-cloner-pousser.md:11
#: src/user_manual/tutorials/03-collaborer.md:11
#: src/user_manual/tutorials/04-automatiser-ci.md:11
#: src/user_manual/how-to/index.md:11
#: src/user_manual/how-to/gerer-cles-ssh.md:11
#: src/user_manual/how-to/configurer-2fa.md:11
#: src/user_manual/how-to/creer-personal-access-token.md:11
#: src/user_manual/how-to/gerer-equipes-permissions.md:11
#: src/user_manual/how-to/ouvrir-pull-request.md:11
#: src/user_manual/how-to/fusionner-strategies.md:11
#: src/user_manual/how-to/utiliser-labels-issues.md:11
#: src/user_manual/how-to/importer-depot-externe.md:11
#: src/user_manual/how-to/consulter-sbom.md:11
#: src/user_manual/reference/index.md:11
#: src/user_manual/reference/modele-permissions.md:11
#: src/user_manual/reference/api-rest-v1.md:11
#: src/user_manual/reference/gitrust-ci-yml-schema.md:11
#: src/user_manual/reference/markdown-et-syntaxe.md:11
#: src/user_manual/reference/notifications.md:11
#: src/user_manual/explanation/index.md:11
#: src/user_manual/explanation/modele-collaboration.md:11
#: src/user_manual/explanation/securite-utilisateur.md:11
#: src/user_manual/explanation/cycle-vie-pull-request.md:11
#: src/administration_manual/tutorials/index.md:11
#: src/administration_manual/tutorials/02-installation-systemd.md:11
#: src/administration_manual/tutorials/03-premier-demarrage.md:11
#: src/administration_manual/how-to/index.md:11
#: src/administration_manual/how-to/sauvegarder-restaurer.md:11
#: src/administration_manual/how-to/mettre-a-jour.md:11
#: src/administration_manual/how-to/configurer-smtp.md:11
#: src/administration_manual/how-to/configurer-oauth.md:11
#: src/administration_manual/how-to/tuner-rate-limiting.md:11
#: src/administration_manual/how-to/forcer-2fa-globalement.md:11
#: src/administration_manual/how-to/depanner-ssh.md:11
#: src/administration_manual/how-to/depanner-ci.md:11
#: src/administration_manual/how-to/gerer-utilisateurs-admin.md:11
#: src/administration_manual/how-to/auditer-instance.md:11
#: src/administration_manual/reference/index.md:11
#: src/administration_manual/reference/variables-environnement.md:11
#: src/administration_manual/reference/schema-base-de-donnees.md:11
#: src/administration_manual/reference/ports-et-services.md:11
#: src/administration_manual/reference/conformite-anssi-pa074.md:11
#: src/administration_manual/explanation/index.md:11
#: src/administration_manual/explanation/architecture-globale.md:11
#: src/administration_manual/explanation/modele-deploiement.md:11
#: src/administration_manual/explanation/ci-dagger.md:11
#: src/administration_manual/explanation/strategie-sauvegarde.md:11
#: src/developer_manual/tutorials/index.md:11
#: src/developer_manual/tutorials/02-premiere-contribution.md:11
#: src/developer_manual/tutorials/03-creer-un-worker-async.md:11
#: src/developer_manual/how-to/index.md:11
#: src/developer_manual/how-to/contribuer-workflow-pr.md:11
#: src/developer_manual/how-to/ajouter-route-web.md:11
#: src/developer_manual/how-to/ajouter-service-metier.md:11
#: src/developer_manual/how-to/ajouter-migration-db.md:11
#: src/developer_manual/how-to/implementer-webhooks.md:11
#: src/developer_manual/how-to/implementer-endpoint-api.md:11
#: src/developer_manual/how-to/passer-la-qa-avant-merge.md:11
#: src/developer_manual/reference/index.md:11
#: src/developer_manual/reference/services-api-interne.md:11
#: src/developer_manual/reference/schema-base-donnees.md:11
#: src/developer_manual/reference/api-rest-v1.md:11
#: src/developer_manual/reference/git-hooks-post-receive.md:11
#: src/developer_manual/reference/rustwarden-core-api.md:11
#: src/developer_manual/explanation/index.md:11
#: src/developer_manual/explanation/modele-permissions-rbac.md:11
#: src/developer_manual/explanation/2fa-fonctionnement.md:11
#: src/developer_manual/explanation/hierarchie-labels.md:11
#: src/developer_manual/explanation/ci-dagger-easy-vs-power.md:11
#: src/developer_manual/explanation/decisions-ui-htmx.md:11
#: src/developer_manual/explanation/patron-worker-async.md:11
msgid "Lier les pages voisines selon les règles de navigation Diátaxis"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:1
msgid ""
"Premiers pas : active la 2FA, ajoute ta clé SSH et crée ton premier dépôt"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:3
#: src/administration_manual/tutorials/01-installation-docker.md:3
#: src/developer_manual/tutorials/01-getting-started.md:5
msgid "Objectifs"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:5
msgid "À la fin de ce tutoriel, tu sauras :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:7
msgid ""
"**O1. Activer** l'authentification à deux facteurs (2FA) sur ton compte "
"gitrust"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:8
msgid ""
"**O2. Enregistrer** une clé SSH publique dans ton profil pour te connecter "
"sans mot de passe"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:9
msgid ""
"**O3. Créer** un dépôt vide et vérifier qu'il est accessible à l'URL attendue"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:11
#: src/administration_manual/tutorials/01-installation-docker.md:11
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:51
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:66
#: src/developer_manual/tutorials/01-getting-started.md:13
#: src/developer_manual/how-to/lancer-tests-e2e.md:5
msgid "Pré-requis"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:13
msgid ""
"**Technique** : un compte gitrust existant (e-mail + mot de passe), Git "
"installé (`git --version` répond), une paire de clés SSH générée ou à "
"générer (`ssh-keygen`)"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:14
msgid ""
"**Pédagogique** : aucun tutoriel préalable requis — c'est le point de départ "
"du parcours"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:15
msgid "**Temps estimé** : ~20 minutes"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:19
msgid ""
"Avant de taper la première commande, prenons 2 minutes pour comprendre ce "
"que tu vas faire et pourquoi."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:21
msgid ""
"**Un dépôt** (_repository_), c'est comme un dossier de projet avec tout "
"l'historique de ses modifications — une boîte d'archives vivante que Git "
"surveille. Sur gitrust, ce dossier vit sur le serveur et peut être partagé "
"avec ton équipe."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:23
msgid ""
"**Une clé SSH** fonctionne comme une serrure et une clé : tu gardes la clé "
"privée sur ta machine (ne la partage jamais), et tu déposes la clé publique "
"dans ton profil gitrust. Ensuite, Git se connecte automatiquement sans te "
"redemander de mot de passe — gitrust reconnaît ta machine."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:25
msgid ""
"**La 2FA** (authentification à deux facteurs) ajoute un second verrou à ton "
"compte : même si quelqu'un vole ton mot de passe, il ne peut pas se "
"connecter sans le code de ton téléphone. C'est une protection essentielle "
"pour tout compte qui héberge du code."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:27
msgid "Voici le flux que tu vas configurer :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:43
msgid "Étape 1 : Connecte-toi et accède aux paramètres de sécurité"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:45
msgid ""
"Ouvre ton navigateur et va sur l'URL de ton instance gitrust (par exemple "
"`https://demo.gitrust.eu`). Connecte-toi avec ton e-mail et ton mot de passe."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:47
msgid ""
"Une fois connecté, clique sur ton avatar en haut à droite, puis sur "
"**Paramètres** (`/settings`). Dans le menu de gauche, sélectionne "
"**Sécurité**."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:49
msgid ""
"**Checkpoint** : tu dois voir la page _Sécurité_ avec une section « "
"Authentification à deux facteurs » et le statut « Désactivée ». Si tu ne la "
"vois pas, vérifie que tu es bien connecté avec le bon compte."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:53
msgid "Étape 2 : Active la 2FA avec une application d'authentification"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:55
msgid ""
"Sur la page _Sécurité_, clique sur **Activer la 2FA**. gitrust affiche un QR "
"code."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:57
msgid ""
"Ouvre ton application d'authentification (Google Authenticator, Authy, ou "
"tout équivalent compatible TOTP)."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:58
msgid "Scanne le QR code avec l'application."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:59
msgid ""
"L'application affiche un code à 6 chiffres qui change toutes les 30 secondes."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:60
msgid ""
"Saisis ce code dans le champ **Code de vérification** et clique "
"**Confirmer**."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:62
#: src/user_manual/tutorials/01-premier-pas.md:124
msgid "Sortie attendue (message dans l'interface) :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:68
msgid ""
"gitrust affiche également **10 codes de secours** (format `XXXX-XXXX`). "
"Copie-les et conserve-les hors ligne — ils te permettent de récupérer "
"l'accès si tu perds ton téléphone."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:70
msgid ""
"**Checkpoint** : retourne sur _Paramètres → Sécurité_. La section 2FA doit "
"maintenant afficher « **Activée** » en vert. Si elle affiche toujours « "
"Désactivée », recommence l'étape en t'assurant que le code à 6 chiffres est "
"saisi avant qu'il expire."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:74
msgid "Étape 3 : Génère ou localise ta clé SSH"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:76
msgid ""
"Si tu n'as pas encore de paire de clés SSH, génère-en une maintenant dans "
"ton terminal :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:79
msgid "\"mon-compte@example.com\""
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:82
#: src/user_manual/tutorials/01-premier-pas.md:135
#: src/administration_manual/tutorials/01-installation-docker.md:196
#: src/administration_manual/tutorials/01-installation-docker.md:215
#: src/administration_manual/tutorials/01-installation-docker.md:251
#: src/developer_manual/tutorials/01-getting-started.md:94
#: src/developer_manual/tutorials/01-getting-started.md:108
#: src/developer_manual/tutorials/01-getting-started.md:173
#: src/developer_manual/tutorials/01-getting-started.md:189
#: src/developer_manual/tutorials/01-getting-started.md:203
#: src/developer_manual/tutorials/01-getting-started.md:224
#: src/developer_manual/tutorials/01-getting-started.md:238
#: src/developer_manual/tutorials/01-getting-started.md:295
msgid "Sortie attendue :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:94
msgid ""
"Appuie sur Entrée pour accepter le chemin par défaut. Tu peux choisir une "
"passphrase ou laisser vide (appuie deux fois sur Entrée). Une passphrase "
"ajoute une couche de sécurité."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:96
msgid ""
"Affiche maintenant ta **clé publique** (le fichier `.pub` — celui-ci est "
"fait pour être partagé) :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:102
msgid "Sortie attendue (une seule ligne) :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:107
msgid "Copie cette ligne entière dans le presse-papier."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:109
msgid ""
"**Checkpoint** : la commande `cat` doit afficher une ligne commençant par "
"`ssh-ed25519` (ou `ssh-rsa` si tu as une clé plus ancienne). Si elle affiche "
"« No such file or directory », la génération n'a pas abouti — relance `ssh-"
"keygen`."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:113
msgid "Étape 4 : Enregistre la clé SSH dans ton profil gitrust"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:115
msgid ""
"Dans ton navigateur, retourne sur _Paramètres_ et clique sur **Clés SSH** "
"dans le menu de gauche."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:117
msgid "Clique sur **Ajouter une clé SSH**. Un formulaire apparaît :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:119
msgid ""
"**Titre** : donne un nom descriptif à cette clé (ex. `laptop-perso-2026`, "
"`poste-bureau`)"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:120
msgid "**Clé** : colle la ligne copiée à l'étape précédente"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:122
msgid "Clique **Enregistrer la clé**."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:129
msgid "Teste maintenant la connexion SSH depuis ton terminal :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:140
msgid ""
"**Checkpoint** : si tu obtiens ce message, ta clé SSH est correctement "
"enregistrée. Si tu obtiens `Permission denied (publickey)`, vérifie que tu "
"as bien copié la clé **publique** (`.pub`) et non la clé privée. Consulte la "
"section « Et si ça ne marche pas » ci-dessous."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:144
msgid "Étape 5 : Crée ton premier dépôt vide"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:146
msgid ""
"Dans ton navigateur, clique sur le **+** en haut à droite (ou navigue vers `/"
"repo/new`)."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:148
msgid "Remplis le formulaire :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:150
msgid "**Propriétaire** : ton pseudo"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:151
msgid ""
"**Nom du dépôt** : `mon-premier-depot` (lettres, chiffres, tirets uniquement)"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:152
msgid "**Visibilité** : Privé (ou Public selon ta préférence)"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:153
msgid "**Initialiser le dépôt** : coche « Ajouter un README »"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:155
msgid "Clique sur **Créer le dépôt**."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:157
msgid "Sortie attendue : gitrust te redirige vers la page du dépôt à l'URL :"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:158
msgid ""
"```\n"
"https://demo.gitrust.eu/tonpseudo/mon-premier-depot\n"
"```"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:162
msgid ""
"La page affiche un fichier `README.md` avec le nom du dépôt, et la barre "
"latérale montre 1 commit, 1 branche (`main`)."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:164
msgid ""
"**Checkpoint** : note l'URL affichée dans la barre d'adresse de ton "
"navigateur. Elle doit correspondre au patron `https://<instance>/<pseudo>/"
"<nom-depot>`. Si tu vois une erreur 404 ou 500, relis le formulaire de "
"création."
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:168
#: src/administration_manual/tutorials/01-installation-docker.md:287
#: src/developer_manual/tutorials/01-getting-started.md:365
msgid "Récapitulatif"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:170
msgid ""
"✓ **O1 accompli** : la 2FA est activée sur ton compte — tu l'as vérifiée sur "
"la page _Sécurité_ qui affiche « Activée »"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:171
msgid ""
"✓ **O2 accompli** : ta clé SSH publique est enregistrée — tu l'as confirmée "
"avec `ssh -T git@... -p 2222` qui a répondu « Vous êtes authentifié »"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:172
msgid ""
"✓ **O3 accompli** : ton premier dépôt est créé et visible à l'URL `/<pseudo>/"
"mon-premier-depot`"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:176
#: src/administration_manual/tutorials/01-installation-docker.md:295
#: src/developer_manual/tutorials/01-getting-started.md:373
msgid "Et si ça ne marche pas"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:178
#: src/administration_manual/tutorials/01-installation-docker.md:297
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:559
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:255
#: src/administration_manual/how-to/integrer-dependency-track.md:303
#: src/administration_manual/how-to/integrer-dependency-track.md:312
#: src/developer_manual/tutorials/01-getting-started.md:375
msgid "Symptôme"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:178
#: src/administration_manual/tutorials/01-installation-docker.md:297
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:255
#: src/administration_manual/how-to/integrer-dependency-track.md:303
#: src/administration_manual/how-to/integrer-dependency-track.md:312
#: src/developer_manual/tutorials/01-getting-started.md:375
msgid "Cause probable"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:178
#: src/administration_manual/tutorials/01-installation-docker.md:297
#: src/developer_manual/tutorials/01-getting-started.md:375
msgid "Correction"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:180
msgid "`Permission denied (publickey)` lors du test SSH"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:180
msgid ""
"Tu as collé la clé privée au lieu de la clé publique, ou le fichier `.pub` "
"ne correspond pas à la clé active"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:180
msgid ""
"Dans gitrust, supprime la clé ajoutée. Retourne au terminal et exécute `ssh-"
"add -l` pour voir les clés actives. Recopie la bonne clé `.pub` avec `cat ~/."
"ssh/id_ed25519.pub`"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:181
msgid "`Connection refused` lors du test SSH"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:181
msgid ""
"Le port SSH de l'instance est différent de 2222, ou l'instance est "
"inaccessible"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:181
msgid ""
"Vérifie avec l'administrateur le port SSH réel. Essaie `ssh -T "
"git@<instance> -p 22` en alternative"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:182
msgid "Le code 2FA est refusé alors qu'il semble correct"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:182
msgid "L'horloge de ton téléphone est désynchronisée (décalage > 30 s)"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:182
msgid ""
"Active la synchronisation automatique de l'heure sur ton téléphone "
"(_Paramètres → Date et heure → Automatique_). Réessaie immédiatement après"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:183
msgid "Le dépôt redirige vers une erreur 422 lors de la création"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:183
msgid "Le nom contient des caractères interdits (espaces, accents, `/`)"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:183
msgid ""
"Utilise uniquement des lettres non accentuées, chiffres et tirets. Évite les "
"points en début ou fin de nom"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:187
#: src/administration_manual/tutorials/01-installation-docker.md:306
#: src/developer_manual/tutorials/01-getting-started.md:383
msgid "Prochaine étape"
msgstr ""

#: src/user_manual/tutorials/01-premier-pas.md:189
msgid ""
"→ [02 — Cloner et pousser du code](02-cloner-pousser.md) : clone ton dépôt "
"en local avec SSH, fais ton premier commit et pousse-le sur gitrust (~25 min)"
msgstr ""

#: src/administration_manual/index.md:3
msgid ""
"Ce manuel s'adresse aux opérateurs et self-hosters qui déploient, "
"configurent et maintiennent une instance gitrust en production. Il couvre "
"l'intégralité du cycle de vie d'une instance : premier démarrage, mise en "
"production, sauvegarde, mise à jour et dépannage. Il suppose des "
"connaissances en administration Linux, en réseau et en TLS — il n'explique "
"pas ces prérequis."
msgstr ""

#: src/administration_manual/index.md:7
msgid ""
"Le parcours administrateur est structuré en 4 tutoriels qui représentent "
"environ 3 heures au total. L'étayage est dégressif : le premier tutoriel "
"fournit tout clé en main, le dernier demande de composer soi-même à partir "
"des recettes disponibles."
msgstr ""

#: src/administration_manual/index.md:18
msgid ""
"**Checkpoint de parcours** : avant de passer au tutoriel 02, vous devez "
"avoir une instance gitrust accessible sur `http://localhost:4000` avec un "
"compte administrateur fonctionnel. Si ce n'est pas le cas, relisez le "
"tutoriel 01."
msgstr ""

#: src/administration_manual/index.md:20
msgid ""
"**Checkpoint de parcours** : avant le tutoriel 04, vous devez avoir une "
"instance démarrée avec une configuration SMTP et un reverse-proxy TLS "
"opérationnel. Si ce n'est pas le cas, relisez le tutoriel 03."
msgstr ""

#: src/administration_manual/index.md:26 src/developer_manual/index.md:25
msgid ""
"Les tutoriels sont guidés pas-à-pas avec des sorties verbatim attendues. "
"Suivez-les dans l'ordre — chacun suppose le précédent complété."
msgstr ""

#: src/administration_manual/index.md:28
msgid ""
"[01 — Installation Docker : stack docker-compose complète](tutorials/01-"
"installation-docker.md) — ~30 min"
msgstr ""

#: src/administration_manual/index.md:29
msgid ""
"[02 — Installation systemd : binaire natif + service](tutorials/02-"
"installation-systemd.md) — ~45 min"
msgstr ""

#: src/administration_manual/index.md:30
msgid ""
"[03 — Premier démarrage : admin bootstrap, migrations](tutorials/03-premier-"
"demarrage.md) — ~20 min"
msgstr ""

#: src/administration_manual/index.md:31
msgid ""
"[04 — Mise en production](tutorials/04-mise-en-production-192-168.md) — ~90 "
"min"
msgstr ""

#: src/administration_manual/index.md:37 src/developer_manual/index.md:35
msgid ""
"Les how-to répondent à « comment faire X » sans explication de fond. "
"Consultez-les dans n'importe quel ordre selon votre besoin."
msgstr ""

#: src/administration_manual/index.md:39
msgid "[Sauvegarder et restaurer](how-to/sauvegarder-restaurer.md)"
msgstr ""

#: src/administration_manual/index.md:40
msgid "[Mettre à jour l'instance](how-to/mettre-a-jour.md)"
msgstr ""

#: src/administration_manual/index.md:41
msgid "[Configurer SMTP](how-to/configurer-smtp.md)"
msgstr ""

#: src/administration_manual/index.md:42
msgid "[Configurer OAuth (Google, GitHub)](how-to/configurer-oauth.md)"
msgstr ""

#: src/administration_manual/index.md:43
msgid ""
"[Configurer un CI runner distant](how-to/configurer-ci-runner-remote.md)"
msgstr ""

#: src/administration_manual/index.md:44
msgid "[Intégrer Dependency-Track (SBOM)](how-to/integrer-dependency-track.md)"
msgstr ""

#: src/administration_manual/index.md:45
msgid "[Durcir avec Fail2ban](how-to/durcir-avec-fail2ban.md)"
msgstr ""

#: src/administration_manual/index.md:46
msgid "[Tuner le rate limiting](how-to/tuner-rate-limiting.md)"
msgstr ""

#: src/administration_manual/index.md:47
msgid "[Forcer la 2FA globalement](how-to/forcer-2fa-globalement.md)"
msgstr ""

#: src/administration_manual/index.md:48
msgid "[Dépanner SSH](how-to/depanner-ssh.md)"
msgstr ""

#: src/administration_manual/index.md:49
msgid "[Dépanner la CI](how-to/depanner-ci.md)"
msgstr ""

#: src/administration_manual/index.md:50
msgid ""
"[Gérer les utilisateurs depuis /admin](how-to/gerer-utilisateurs-admin.md)"
msgstr ""

#: src/administration_manual/index.md:51
msgid "[Auditer l'instance](how-to/auditer-instance.md)"
msgstr ""

#: src/administration_manual/index.md:57
msgid ""
"La référence documente de façon exhaustive les paramètres, schémas et "
"comportements. Elle est destinée à la consultation ponctuelle."
msgstr ""

#: src/administration_manual/index.md:59
msgid ""
"[Variables d'environnement (.env)](reference/variables-environnement.md)"
msgstr ""

#: src/administration_manual/index.md:60
msgid ""
"[Paramètres dynamiques (app_settings)](reference/parametres-dynamiques.md)"
msgstr ""

#: src/administration_manual/index.md:61
msgid "[Schéma de base de données](reference/schema-base-de-donnees.md)"
msgstr ""

#: src/administration_manual/index.md:62
msgid ""
"[Ports et services (4000 HTTP, 2222 SSH, 5432 PG)](reference/ports-et-"
"services.md)"
msgstr ""

#: src/administration_manual/index.md:63
msgid "[Conformité ANSSI PA-074](reference/conformite-anssi-pa074.md)"
msgstr ""

#: src/administration_manual/index.md:69
msgid ""
"Les explanations construisent les modèles mentaux nécessaires pour prendre "
"de bonnes décisions d'exploitation. Lisez-les quand vous voulez comprendre "
"les choix d'architecture, pas seulement les appliquer."
msgstr ""

#: src/administration_manual/index.md:71
msgid "[Architecture globale de gitrust](explanation/architecture-globale.md)"
msgstr ""

#: src/administration_manual/index.md:72
msgid ""
"[Modèle de déploiement : mono-machine vs HA](explanation/modele-deploiement."
"md)"
msgstr ""

#: src/administration_manual/index.md:73
msgid "[CI Dagger : pourquoi et comment](explanation/ci-dagger.md)"
msgstr ""

#: src/administration_manual/index.md:74
msgid ""
"[Stratégie de sauvegarde 3-2-1 adaptée gitrust](explanation/strategie-"
"sauvegarde.md)"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:1
msgid ""
"Installation Docker : démarrez gitrust en 30 minutes avec docker-compose"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:5
#: src/developer_manual/tutorials/01-getting-started.md:7
msgid "À la fin de ce tutoriel, vous saurez :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:7
msgid ""
"**O1. Déployer** la stack gitrust minimale (application + PostgreSQL) avec "
"docker-compose"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:8
msgid ""
"**O2. Vérifier** que les trois services démarrent correctement et sont en "
"bonne santé"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:9
msgid ""
"**O3. Créer** le premier compte administrateur et accéder à l'interface web"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:13
msgid ""
"**Technique** : une VM ou machine Linux (Debian 12 / Ubuntu 22.04 ou "
"supérieur), Docker Engine ≥ 24 installé (`docker --version` répond), Docker "
"Compose plugin installé (`docker compose version` répond), ports 4000 et "
"2222 libres sur la machine"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:14
msgid ""
"**Pédagogique** : aucun tutoriel gitrust préalable requis — c'est le point "
"de départ du parcours administrateur"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:15
msgid "**Temps estimé** : ~30 minutes"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:19
msgid ""
"Avant de lancer la moindre commande, comprenons ce que docker-compose va "
"orchestrer et pourquoi."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:21
msgid ""
"gitrust est composé de **trois services principaux** dans sa configuration "
"minimale. Pensez-y comme trois pièces d'un appartement qui s'appellent entre "
"elles via un réseau interne :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:23
msgid ""
"```mermaid\n"
"graph TB\n"
"    subgraph internet [\"Internet / votre navigateur\"]\n"
"        B[Navigateur :4000]\n"
"        S[Client git/SSH :2222]\n"
"    end\n"
"\n"
"    subgraph docker [\"Réseau Docker gitrust_net\"]\n"
"        A[\"gitrust-app<br/>(Rust, port 4000 + 2222)<br/>Lit la config "
"depuis .env\"]\n"
"        P[\"postgres<br/>(PostgreSQL 16, port 5432)<br/>Stocke comptes, "
"dépôts, issues\"]\n"
"        R[\"redis (optionnel)<br/>(Redis 7, port 6379)<br/>Sessions web + "
"cache\"]\n"
"    end\n"
"\n"
"    B -->|HTTP| A\n"
"    S -->|SSH| A\n"
"    A -->|SQL| P\n"
"    A -.->|sessions| R\n"
"```"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:42
msgid ""
"**gitrust-app** est le cœur : serveur HTTP (`:4000`) + serveur SSH (`:2222`) "
"compilé en Rust. Il lit sa configuration depuis un fichier `.env` et écrit "
"les dépôts Git bare sur un volume Docker. **PostgreSQL** stocke toutes les "
"données relationnelles (comptes, organisations, dépôts, issues, PRs). "
"**Redis** est optionnel dans la configuration minimale — il gère les "
"sessions web et le cache quand il est présent."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:44
msgid ""
"Dans ce tutoriel, nous utilisons la stack **minimale** (app + PostgreSQL) "
"suffisante pour évaluer gitrust et démarrer une petite instance. La stack "
"production avec Redis et SMTP se trouve dans [`template/docker/docker-"
"compose.production.yml`](../../template/docker/docker-compose.production."
"yml)."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:48
msgid "Étape 1 : Créez le répertoire de travail et le fichier de configuration"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:50
msgid ""
"Créez un répertoire dédié à votre instance gitrust et positionnez-vous "
"dedans :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:56
msgid ""
"Créez le fichier de configuration `.env` avec les valeurs minimales. "
"**Changez impérativement** les valeurs marquées `CHANGE_ME` :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:59
msgid ""
"<< 'EOF'\n"
"# === gitrust — configuration minimale ===\n"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:62
msgid "# Clé secrète de l'application (générez avec : openssl rand -hex 32)\n"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:65
msgid "# URL publique de l'instance (sans slash final)\n"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:68
msgid "# Base de données PostgreSQL\n"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:70
msgid ""
"POSTGRES_USER=gitrust\n"
"POSTGRES_PASSWORD=CHANGE_ME_db_password\n"
"POSTGRES_DB=gitrust\n"
"\n"
"# Serveur SSH (port exposé à l'extérieur)\n"
"SSH_PORT=2222\n"
"\n"
"# Mode de l'application\n"
"RUST_LOG=info\n"
"APP_ENV=production\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:84
msgid ""
"Générez maintenant une clé secrète robuste et remplacez la valeur dans `."
"env` :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:87
msgid "$(openssl rand -hex 32)"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:88
msgid "\"s/CHANGE_ME_openssl_rand_hex_32/$SECRET/\""
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:91
msgid ""
"Choisissez également un mot de passe pour PostgreSQL et remplacez les deux "
"occurrences :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:94
msgid "$(openssl rand -hex 16)"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:95
msgid "\"s/CHANGE_ME_db_password/$DB_PASS/g\""
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:98
msgid "Sortie attendue (vérification) :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:100
msgid ""
"# → "
"SECRET_KEY=4a7f2c9e1b8d3f6a0e5c2b9d7f4a1e8c3b6d9f2a5e8c1b4d7f0a3e6c9b2d5f8a\n"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:104
msgid ""
"**Checkpoint** : exécutez `grep CHANGE_ME .env` — la commande doit ne rien "
"retourner. Si elle retourne des lignes, ces valeurs n'ont pas été remplacées "
"et le démarrage échouera."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:108
msgid "Étape 2 : Créez le fichier docker-compose.yml"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:110
msgid ""
"Créez le fichier `docker-compose.yml` suivant dans `/opt/gitrust/`. Ce "
"contenu correspond à la stack minimale gitrust — il est reproduit ici "
"intégralement pour que vous puissiez démarrer sans dépendance externe :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:113
msgid ""
"<< 'EOF'\n"
"# docker-compose.minimal.yml — Stack gitrust minimale (app + PostgreSQL)\n"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:115
msgid ""
"'usage : évaluation, développement, petite instance (<10 utilisateurs)\n"
"# Pour la production : utilisez docker-compose.production.yml (+ Redis + "
"SMTP)\n"
"#\n"
"# Usage :\n"
"#   docker compose up -d\n"
"#   docker compose logs -f gitrust\n"
"#   docker compose down\n"
"\n"
"version: \"3.9\"\n"
"\n"
"services:\n"
"  # ── Base de données "
"───────────────────────────────────────────────────────\n"
"  postgres:\n"
"    image: postgres:16-alpine\n"
"    container_name: gitrust_postgres\n"
"    restart: unless-stopped\n"
"    environment:\n"
"      POSTGRES_USER: ${POSTGRES_USER}\n"
"      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}\n"
"      POSTGRES_DB: ${POSTGRES_DB}\n"
"    volumes:\n"
"      # Données persistantes — ne supprimez pas ce volume sans sauvegarde\n"
"      - postgres_data:/var/lib/postgresql/data\n"
"    healthcheck:\n"
"      test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER} -d "
"${POSTGRES_DB}\"]\n"
"      interval: 10s\n"
"      timeout: 5s\n"
"      retries: 5\n"
"    networks:\n"
"      - gitrust_net\n"
"\n"
"  # ── Application gitrust "
"───────────────────────────────────────────────────\n"
"  gitrust:\n"
"    image: ghcr.io/gitrust/gitrust:latest\n"
"    container_name: gitrust_app\n"
"    restart: unless-stopped\n"
"    depends_on:\n"
"      postgres:\n"
"        condition: service_healthy\n"
"    env_file:\n"
"      # Lit toutes les variables depuis .env — ne commitez jamais ce "
"fichier\n"
"      - .env\n"
"    ports:\n"
"      # Interface web — exposée sur toutes les interfaces de la machine "
"hôte\n"
"      - \"4000:4000\"\n"
"      # Serveur SSH Git — exposé sur le port configuré dans .env\n"
"      - \"${SSH_PORT:-2222}:2222\"\n"
"    volumes:\n"
"      # Dépôts Git bare — données critiques, sauvegardez ce volume\n"
"      - git_repos:/var/lib/gitrust/repositories\n"
"      # Clés SSH du serveur — générées au premier démarrage, persistez-les\n"
"      - ssh_host_keys:/etc/gitrust/ssh\n"
"    healthcheck:\n"
"      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:4000/health\"]\n"
"      interval: 30s\n"
"      timeout: 10s\n"
"      retries: 3\n"
"      start_period: 30s\n"
"    networks:\n"
"      - gitrust_net\n"
"\n"
"volumes:\n"
"  # postgres_data : données relationnelles (comptes, dépôts, issues, PRs)\n"
"  postgres_data:\n"
"  # git_repos : dépôts Git bare (le contenu réel des commits)\n"
"  git_repos:\n"
"  # ssh_host_keys : clés SSH hôte (fingerprint de votre serveur)\n"
"  ssh_host_keys:\n"
"\n"
"networks:\n"
"  gitrust_net:\n"
"    driver: bridge\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:190
msgid ""
"**Checkpoint** : vérifiez que les deux fichiers sont présents dans `/opt/"
"gitrust/` :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:207
msgid "Étape 3 : Démarrez la stack et suivez les logs"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:209
msgid "Démarrez tous les services en arrière-plan :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:216
msgid ""
"```\n"
"[+] Running 4/4\n"
" ✔ Network gitrust_gitrust_net    Created                          0.1s\n"
" ✔ Volume \"gitrust_postgres_data\" Created                          0.0s\n"
" ✔ Container gitrust_postgres     Started                          0.8s\n"
" ✔ Container gitrust_app          Started                          1.2s\n"
"```"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:224
msgid ""
"Suivez les logs de l'application pour observer le démarrage (les migrations "
"s'exécutent automatiquement) :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:230
msgid "Sortie attendue (les 15-20 premières secondes) :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:243
msgid ""
"Appuyez sur **Ctrl+C** pour quitter le suivi des logs (les containers "
"continuent de tourner)."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:245
msgid "**Checkpoint** : vérifiez l'état de santé des services :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:252
msgid ""
"```\n"
"NAME              IMAGE                          COMMAND                  "
"SERVICE    CREATED         STATUS                   PORTS\n"
"gitrust_app       ghcr.io/gitrust/gitrust:latest \"/usr/local/bin/gitr…\"  "
"gitrust    2 minutes ago   Up 2 minutes (healthy)   0.0.0.0:4000->4000/tcp, "
"0.0.0.0:2222->2222/tcp\n"
"gitrust_postgres  postgres:16-alpine             \"docker-entrypoint.s…\"  "
"postgres   2 minutes ago   Up 2 minutes (healthy)   5432/tcp\n"
"```"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:258
msgid ""
"Les deux containers doivent afficher `(healthy)`. Si l'un affiche "
"`(starting)`, attendez 30 secondes et relancez la commande. S'il affiche "
"`(unhealthy)`, consultez les logs avec `docker compose logs gitrust` ou "
"`docker compose logs postgres`."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:262
msgid "Étape 4 : Créez le premier compte administrateur"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:264
msgid "Ouvrez votre navigateur et rendez-vous sur `http://localhost:4000`."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:266
msgid ""
"Vous devriez voir la page d'accueil gitrust avec un formulaire "
"d'inscription. Comme l'instance est vierge, **le premier compte créé devient "
"automatiquement administrateur**."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:268
msgid "Remplissez le formulaire :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:269
msgid "**Pseudo** : votre identifiant administrateur (ex. `admin`)"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:270
msgid "**E-mail** : votre adresse e-mail"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:271
msgid "**Mot de passe** : choisissez un mot de passe robuste (≥ 12 caractères)"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:273
msgid "Cliquez sur **Créer mon compte**."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:275
msgid ""
"Sortie attendue dans les logs (visible avec `docker compose logs -f "
"gitrust`) :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:281
msgid ""
"**Checkpoint final** : connectez-vous avec vos identifiants. Après la "
"connexion, vérifiez que le menu en haut à droite affiche un lien "
"**Administration** (ou naviguez vers `http://localhost:4000/admin`). Cette "
"page n'est accessible qu'aux administrateurs — sa présence confirme que "
"votre compte a bien le rôle admin."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:283
msgid ""
"L'URL de votre instance est `http://localhost:4000` et votre compte "
"administrateur est opérationnel."
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:289
msgid ""
"✓ **O1 accompli** : la stack docker-compose est déployée — `docker compose "
"ps` affiche deux containers `(healthy)`"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:290
msgid ""
"✓ **O2 accompli** : les trois services (app, PostgreSQL, réseau interne) "
"démarrent correctement — les logs montrent « gitrust is ready » et les "
"migrations sont appliquées"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:291
msgid ""
"✓ **O3 accompli** : le premier compte administrateur est créé et la page `/"
"admin` est accessible"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:299
msgid "`Error: port 4000 is already in use` au démarrage"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:299
msgid "Un autre service occupe le port 4000 sur la machine hôte"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:299
msgid ""
"Identifiez le service avec `ss -tlnp \\| grep 4000` ou `lsof -i :4000`. "
"Arrêtez-le ou changez le port dans `docker-compose.yml` : remplacez "
"`\"4000:4000\"` par `\"4001:4000\"` et accédez sur `:4001`"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:300
msgid "Le container `gitrust_app` affiche `(unhealthy)` ou redémarre en boucle"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:300
msgid ""
"La variable `DATABASE_URL` est incorrecte ou `SECRET_KEY` contient des "
"caractères spéciaux non échappés"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:300
msgid ""
"Vérifiez avec `docker compose logs gitrust \\| grep ERROR`. Assurez-vous que "
"`SECRET_KEY` est bien une chaîne hexadécimale sans guillemets. Rechargez "
"avec `docker compose down && docker compose up -d`"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:301
msgid "La page `http://localhost:4000` affiche « Connection refused »"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:301
msgid ""
"Le container n'est pas encore en `(healthy)` ou le port n'est pas exposé"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:301
msgid ""
"Attendez 30 secondes et rechargez. Si le problème persiste, vérifiez que "
"votre pare-feu local (`ufw status`) autorise le port 4000"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:302
msgid ""
"`FATAL: password authentication failed for user \"gitrust\"` dans les logs "
"postgres"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:302
msgid ""
"Le mot de passe dans `DATABASE_URL` ne correspond pas à `POSTGRES_PASSWORD`"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:302
msgid ""
"Supprimez le volume PostgreSQL (`docker compose down -v`) et relancez — "
"**attention : supprime toutes les données**"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:308
msgid ""
"→ [02 — Installation systemd : binaire natif + service](02-installation-"
"systemd.md) : découvrez l'installation sans Docker pour un déploiement "
"production avec hardening AppArmor (~45 min)"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:310
msgid "Ou si vous souhaitez rendre cette instance accessible depuis Internet :"
msgstr ""

#: src/administration_manual/tutorials/01-installation-docker.md:312
msgid ""
"→ [04 — Mise en production](04-mise-en-production-192-168.md) : reverse-"
"proxy TLS, SMTP, sauvegarde automatique (~90 min)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:1
msgid "Mise en production sur une machine Linux avec HTTPS Let's Encrypt"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:3
msgid "Contexte"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:5
msgid ""
"Procédure de référence pour déployer une instance gitrust sur une machine "
"Linux à IP fixe, avec patte externe routée et HTTPS via Let's Encrypt. "
"Reproductible et testée en conditions réelles."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:7
msgid "Adaptez les valeurs suivantes à votre environnement :"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:9
msgid "Placeholder"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:9
msgid "Remplacez par"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:11
msgid "`<your-server-ip>`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:11
msgid ""
"L'IP fixe de votre serveur (ex: `192.168.1.57` sur un LAN, ou une IP "
"publique)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:12
msgid "`<your-domain>`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:12
msgid "Votre FQDN principal (ex: `gitrust.example.com`)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:13
msgid "`<acme-email>`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:13
msgid "L'email pour Let's Encrypt (ex: `contact@example.com`)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:14
msgid "`<admin-user>`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:14
msgid "L'utilisateur SSH admin sur le serveur cible"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:16
msgid "Les trois services gitrust"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:18
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:506
msgid "\\#"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:18
#: src/developer_manual/how-to/contribuer-a-rustwarden.md:7
msgid "Service"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:18
msgid "Bind interne"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:18
msgid "Exposition publique"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:18
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:82
msgid "Variable"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:20
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:277
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:552
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:508
#: src/developer_manual/how-to/importer-depot-externe-code.md:97
msgid "1"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:20
msgid "Web HTTP (UI SSR + API)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:20
msgid "`127.0.0.1:4000`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:20
msgid "`:443` HTTPS via Nginx"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:20
msgid "`SERVER_PORT`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:21
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:509
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:510
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:511
msgid "2"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:21
msgid "SSH Git (russh)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:21
msgid "`127.0.0.1:2222`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:21
msgid "`:22` via Nginx stream"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:21
msgid "`SSH_PORT`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:22
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:508
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:510
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:516
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:520
#: src/developer_manual/how-to/importer-depot-externe-code.md:98
msgid "3"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:22
msgid "Worker CI/CD (Dagger)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:22
msgid "tâche Tokio in-process"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:22
msgid "— (déclenché par push)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:22
#: src/developer_manual/reference/architecture-crates.md:237
msgid "`CI_ENABLED`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:24
msgid ""
"PostgreSQL = dépendance, conteneur Docker bind loopback `127.0.0.1:5432`."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:26
msgid "Topologie réseau"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:45
msgid "Risque critique — ordre d'exécution"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:47
msgid ""
"Le déplacement de `sshd` système de `:22` vers `:2022` **doit** être fait "
"avant la configuration `nginx stream`, et **doit** être validé depuis une "
"**deuxième session SSH** avant fermeture de la première. Sinon : lockout "
"total (besoin d'accès console physique)."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:53
msgid "Poste de build (machine locale avec le code source)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:56
msgid "# Installer si besoin : sudo apt install rsync gettext-base\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:60
msgid "Cible `<your-server-ip>`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:62
msgid "Debian/Ubuntu récent"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:63
msgid "Accès SSH avec `sudo`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:64
msgid "Docker + plugin compose (`docker compose version`)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:65
msgid "Snap ou apt pour `certbot` + plugin nginx"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:66
msgid ""
"DNS `<your-domain>` → IP publique de la patte externe (vérifier `dig +short "
"<your-domain>`)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:67
msgid ""
"Module `stream` Nginx disponible (paquet `libnginx-mod-stream` sur Debian)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:71
msgid "Phase 0 — Générer `.env.production` (poste de build, une seule fois)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:74
msgid "$(openssl rand -hex 64)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:75
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:76
msgid "$(openssl rand -base64 24)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:78
msgid ""
"<<EOF\n"
"# ---- Base de données ----\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:81
msgid "# ---- Serveur HTTP (derrière Nginx HTTPS) ----\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:83
msgid ""
"SERVER_PORT=4000\n"
"\n"
"# ---- Serveur SSH (derrière nginx stream :22) ----\n"
"SSH_PORT=2222\n"
"SSH_LISTEN_ADDR=127.0.0.1\n"
"SSH_PUBLIC_HOST=<your-domain>\n"
"SSH_HOST_KEY_PATH=/opt/gitrust/data/ssh_host_ed25519_key\n"
"\n"
"# ---- Chemins (réécrits par deploy.sh) ----\n"
"GIT_REPOS_BASE_PATH=/opt/gitrust/data/repos\n"
"STATIC_FILES_PATH=/opt/gitrust/static\n"
"\n"
"# ---- Sécurité — HTTPS actif ----\n"
"JWT_SECRET=${JWT}\n"
"JWT_EXPIRATION_MINUTES=15\n"
"REFRESH_TOKEN_EXPIRATION_DAYS=7\n"
"COOKIE_SECURE=true            # HTTPS via Nginx\n"
"COOKIE_SAME_SITE=Lax\n"
"APP_DEBUG=false\n"
"RUST_LOG=info\n"
"\n"
"# ---- Admin initial ----\n"
"ADMIN_USERNAME=admin\n"
"ADMIN_EMAIL=<acme-email>\n"
"ADMIN_PASSWORD=${ADMIN_PWD}\n"
"\n"
"# ---- Inscription & UI ----\n"
"ALLOW_REGISTRATION=false\n"
"APP_NAME=Gitrust\n"
"DEFAULT_LOCALE=fr\n"
"\n"
"# ---- Email ----\n"
"EMAIL_VALIDATION_REQUIRED=false\n"
"EMAIL_BASE_URL=https://<your-domain>\n"
"\n"
"# ---- CI/CD Dagger (worker 3) ----\n"
"CI_ENABLED=true\n"
"CI_MAX_CONCURRENT=4\n"
"CI_DEFAULT_TIMEOUT=3600\n"
"CI_WORKSPACE_PATH=/tmp/gitrust-ci\n"
"CI_REMOTE_HOST=localhost\n"
"\n"
"# ---- Worker import ----\n"
"IMPORT_MAX_CONCURRENT=2\n"
"IMPORT_TIMEOUT_SECS=1800\n"
"DB_WORKER_POOL_SIZE=4\n"
"EOF\n"
"\n"
"chmod 600 .env.production\n"
"echo \"ADMIN_PASSWORD = ${ADMIN_PWD}\"\n"
"echo \"POSTGRES_PASSWORD = ${PG_PWD}\"\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:137
msgid ""
"**Critique** : noter `ADMIN_PASSWORD` et `POSTGRES_PASSWORD` dans un "
"gestionnaire de mots de passe."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:141
msgid "Phase 1 — Préparer la cible : déplacer sshd système sur :2022"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:143
msgid "**À faire en gardant deux sessions SSH simultanées**."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:145
msgid "1.pre. Diagnostic de l'état initial"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:147
msgid "1.pre.1 — Trouver le port SSH ouvert depuis le poste de build"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:150
msgid "# Depuis votre poste (sans être connecté) :\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:152
msgid "\"echo >/dev/tcp/<your-server-ip>/$p\""
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:158
msgid "1.pre.2 — Se connecter sur le port détecté"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:161
msgid "# Cas le plus probable : sshd est sur :22 par défaut\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:165
msgid "1.pre.3 — Une fois connecté, vérifier l'état sshd actuel"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:168
msgid "# Sur quel(s) port(s) sshd écoute-t-il ?\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:170
msgid "# Contenu de la config\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:172
msgid "'^[[:space:]]*Port[[:space:]]+[0-9]+'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:173
msgid "# Statut du service\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:178
msgid "1a. Session 1 : modifier la config sshd"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:184
msgid ""
"<<'EOF'\n"
"Port 2022\n"
"EOF\n"
"\n"
"# Vérifier la syntaxe\n"
"sudo sshd -t\n"
"\n"
"# Si OK, reload (ne déconnecte pas la session courante)\n"
"sudo systemctl reload ssh\n"
"sudo ss -tlnp | grep -E ':22\\b|:2022\\b'\n"
"# Attendu : sshd écoute sur 22 ET 2022\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:197
msgid "1b. Session 2 : valider le nouveau port"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:199
msgid "Depuis le poste de build, **dans un autre terminal** :"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:202
msgid "'echo \"OK port 2022\"'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:202
msgid "# Doit afficher : OK port 2022\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:206
msgid "1c. (Plus tard, après Phase 5) Fermer le port 22 du sshd système"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:208
msgid "Une fois `nginx stream :22` actif et testé :"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:212
msgid ""
"'s/^Port 22$/# Port 22 (déplacé vers 2022, :22 utilisé par nginx stream)/'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:216
msgid "1d. Firewall"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:219
msgid ""
"<<'EOF'\n"
"sudo ufw allow 80/tcp comment 'HTTP ACME + redirect'\n"
"sudo ufw allow 443/tcp comment 'HTTPS Gitrust'\n"
"sudo ufw allow 22/tcp comment 'SSH Git via nginx stream'\n"
"sudo ufw allow 2022/tcp comment 'SSH admin système'\n"
"sudo ufw status numbered\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:228
msgid "Mettre à jour `~/.ssh/config` côté poste dev :"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:235
msgid "Le reste du plan utilise `ssh gitrust-host`."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:239
msgid "Phase 2 — PostgreSQL (Docker, loopback)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:244
msgid ""
"<<EOF\n"
"sudo mkdir -p /opt/gitrust/database\n"
"sudo mv /tmp/pg-compose.yml /opt/gitrust/database/docker-compose.yml\n"
"echo 'POSTGRES_PASSWORD=${PG_PWD}' | sudo tee /opt/gitrust/database/.env >/"
"dev/null\n"
"sudo chmod 600 /opt/gitrust/database/.env\n"
"cd /opt/gitrust/database && sudo docker compose up -d\n"
"sudo docker compose ps\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:254
msgid ""
"Remplacer `${PG_PWD}` par la valeur réelle. Vérifier que le port n'est pas "
"exposé publiquement :"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:257
msgid "'sudo ss -tlnp | grep 5432'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:257
msgid "# Attendu : 127.0.0.1:5432 — PAS 0.0.0.0\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:263
msgid "Phase 3 — Build + déploiement gitrust via `deploy.sh`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:265
msgid "3a. Préparer `deployment/deploy.conf`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:268
msgid ""
"# Éditer DEPLOY_TARGET=gitrust-host, DEPLOY_REMOTE_PATH=/opt/gitrust, "
"DEPLOY_FQDN_INITIAL=<your-domain>\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:274
msgid "3b. Validation du build seul (optionnel)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:280
msgid "3c. Déploiement"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:283
msgid ""
"# Sans argument : utilise DEPLOY_TARGET du deploy.conf (gitrust-host via ~/."
"ssh/config, port 2022)\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:287
msgid ""
"Ce que fait `deploy.sh` : `cargo build --release`, `tailwindcss --minify`, "
"adapte `gitrust.service` + `.env`, rsync, crée user `gitrust`, installe "
"systemd, restart."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:289
msgid ""
"À la fin : gitrust écoute sur `127.0.0.1:4000` (HTTP) et `127.0.0.1:2222` "
"(SSH)."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:292
msgid ""
"'sudo systemctl status gitrust --no-pager && sudo ss -tlnp | grep -E \"4000|"
"2222\"'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:292
msgid "# Attendu : 127.0.0.1:4000 et 127.0.0.1:2222 (PAS 0.0.0.0)\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:298
msgid "Phase 4 — Nginx HTTP + Let's Encrypt"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:300
msgid "4a. Installer nginx + certbot"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:303
msgid ""
"<<'EOF'\n"
"sudo apt update\n"
"sudo apt install -y nginx libnginx-mod-stream certbot python3-certbot-nginx\n"
"sudo systemctl enable --now nginx\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:310
msgid "4b. Déployer la conf Nginx"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:315
msgid ""
"<<EOF\n"
"sudo sed -i 's/gitrust.nuage.ebii/<your-domain>/g' /tmp/gitrust-nginx.conf\n"
"sudo mv /tmp/gitrust-nginx.conf /etc/nginx/sites-available/gitrust\n"
"sudo ln -sf /etc/nginx/sites-available/gitrust /etc/nginx/sites-enabled/"
"gitrust\n"
"sudo rm -f /etc/nginx/sites-enabled/default\n"
"sudo mkdir -p /var/www/html/.well-known/acme-challenge\n"
"sudo nginx -t && sudo systemctl reload nginx\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:325
msgid "4c. Émettre le certificat Let's Encrypt"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:328
msgid ""
"'sudo certbot --nginx \\\n"
"    -d <your-domain> \\\n"
"    --email <acme-email> \\\n"
"    --agree-tos \\\n"
"    --no-eff-email \\\n"
"    --redirect'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:336
msgid "4d. Vérifier le renouvellement automatique"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:339
msgid "'sudo systemctl list-timers | grep certbot'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:340
msgid "'sudo certbot renew --dry-run'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:343
msgid "4e. Test HTTPS"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:346
msgid "# Attendu : HTTP/2 200 (ou 302 vers /login)\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:348
msgid "# Vérifier HSTS\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:355
msgid "Phase 5 — Exposer SSH Git sur :22 via Nginx stream"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:357
msgid "5a. Ajouter le bloc stream"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:360
msgid ""
"<<'EOF'\n"
"sudo nginx -V 2>&1 | grep -o with-stream\n"
"\n"
"sudo tee -a /etc/nginx/nginx.conf <<'NGINX'\n"
"\n"
"# --- Gitrust SSH (proxy :22 -> :2222) "
"-----------------------------------------\n"
"stream {\n"
"    upstream gitrust_ssh {\n"
"        server 127.0.0.1:2222;\n"
"    }\n"
"    server {\n"
"        listen 22;\n"
"        listen [::]:22;\n"
"        proxy_pass gitrust_ssh;\n"
"        proxy_timeout 1h;\n"
"        proxy_connect_timeout 30s;\n"
"        error_log /var/log/nginx/gitrust-ssh.log;\n"
"    }\n"
"}\n"
"NGINX\n"
"\n"
"sudo nginx -t && sudo systemctl restart nginx\n"
"sudo ss -tlnp | grep -E ':22\\b|:2222\\b'\n"
"# Attendu : nginx :22, gitrust :2222 (loopback)\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:387
msgid "5b. Désactiver sshd système sur :22 (Phase 1c)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:390
msgid ""
"<<'EOF'\n"
"sudo sed -i 's/^Port 22$/# Port 22 déplacé/' /etc/ssh/sshd_config 2>/dev/"
"null || true\n"
"sudo systemctl restart ssh\n"
"sudo ss -tlnp | grep -E ':22\\b|:2022\\b'\n"
"# Attendu : nginx :22, sshd :2022 — plus de sshd:22\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:398
msgid "5c. Test clone Git"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:401
msgid ""
"# Dans l'UI gitrust : Settings -> SSH keys -> coller ~/.ssh/id_ed25519.pub\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:406
msgid "\"# test\""
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:414
msgid "Phase 6 — Vérifications globales"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:417
msgid "# Service systemd\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:418
msgid "'sudo systemctl status gitrust --no-pager'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:419
msgid "# Logs (recherche d'erreurs)\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:421
msgid ""
"'sudo journalctl -u gitrust -n 100 --no-pager | grep -iE \"error|warn|fail\"'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:422
msgid "# Ports d'écoute (vue d'ensemble)\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:424
msgid "'sudo ss -tlnp'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:424
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:425
msgid "# Attendu :\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:426
msgid "#   :80    nginx\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:428
msgid "#   :2022  sshd système\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:430
msgid "#   127.0.0.1:4000  gitrust\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:433
msgid "# Renouvellement TLS automatique\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:435
msgid "'sudo systemctl status certbot.timer --no-pager'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:436
msgid "# Test E2E\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:439
msgid "# Banner SSH russh attendu\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:444
msgid "Phase 7 — Durcissement : Fail2ban"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:446
msgid ""
"Voir `administration_manual/how-to/durcir-avec-fail2ban.md` pour la "
"configuration complète."
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:448
msgid "7a. Installation"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:451
msgid ""
"<<'EOF'\n"
"sudo apt install -y fail2ban\n"
"sudo systemctl enable --now fail2ban\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:457
msgid "7b. Configuration minimale rapide"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:460
msgid ""
"<<'EOF'\n"
"[DEFAULT]\n"
"backend  = systemd\n"
"bantime  = 1h\n"
"findtime = 10m\n"
"maxretry = 5\n"
"ignoreip = 127.0.0.1/8 ::1\n"
"banaction          = ufw\n"
"banaction_allports = ufw\n"
"\n"
"[sshd]\n"
"enabled  = true\n"
"port     = 2022\n"
"filter   = sshd\n"
"backend  = %(sshd_backend)s\n"
"logpath  = %(sshd_log)s\n"
"maxretry = 3\n"
"\n"
"[nginx-http-auth]\n"
"enabled  = true\n"
"port     = http,https\n"
"filter   = nginx-http-auth\n"
"logpath  = /var/log/nginx/gitrust.error.log\n"
"\n"
"[gitrust-login]\n"
"enabled  = true\n"
"port     = http,https\n"
"filter   = gitrust-login\n"
"logpath  = /var/log/nginx/gitrust.access.log\n"
"maxretry = 5\n"
"\n"
"[gitrust-ssh]\n"
"enabled      = true\n"
"port         = 22,2222\n"
"filter       = gitrust-ssh\n"
"backend      = systemd\n"
"journalmatch = _SYSTEMD_UNIT=gitrust.service\n"
"maxretry     = 5\n"
"\n"
"[recidive]\n"
"enabled   = true\n"
"logpath   = /var/log/fail2ban.log\n"
"banaction = %(banaction_allports)s\n"
"bantime   = 1w\n"
"findtime  = 1d\n"
"maxretry  = 3\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:509
msgid "Créer les filtres gitrust-login et gitrust-ssh, puis :"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:512
msgid "'sudo systemctl restart fail2ban && sudo fail2ban-client status'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:517
msgid "Phase 8 — Mise à jour vers un nouveau domaine (quand DNS prêt)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:519
msgid "8a. Ajouter le SAN au certificat existant"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:522
msgid ""
"'sudo certbot --nginx --expand \\\n"
"    -d <your-domain> \\\n"
"    -d <new-domain> \\\n"
"    --email <acme-email> \\\n"
"    --agree-tos --no-eff-email'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:529
msgid "8b. Mettre à jour la conf Nginx"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:532
msgid ""
"<<EOF\n"
"sudo sed -i 's/server_name <your-domain>;/server_name <your-domain> <new-"
"domain>;/g' /etc/nginx/sites-available/gitrust\n"
"sudo nginx -t && sudo systemctl reload nginx\n"
"EOF\n"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:538
msgid "8c. Mettre à jour `.env.production` et redéployer"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:541
msgid "'s|SSH_PUBLIC_HOST=.*|SSH_PUBLIC_HOST=<new-domain>|'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:542
msgid "'s|EMAIL_BASE_URL=.*|EMAIL_BASE_URL=https://<new-domain>|'"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:548
msgid "Phase 9 — Mises à jour ultérieures"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:557
msgid "Dépannage"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:559
msgid "Diagnostic"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:559
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:255
msgid "Fix"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:561
msgid "Lockout SSH après reload sshd"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:561
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:84
msgid "—"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:561
msgid "Console physique / KVM IPMI"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:562
msgid "Cert Let's Encrypt échoue (`Connection refused`)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:562
msgid "`dig +short <your-domain>` ≠ IP publique"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:562
msgid "Corriger DNS, ou vérifier que :80 traverse bien le NAT"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:563
msgid "Cert échoue (`unauthorized`)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:563
msgid "Nginx `:80` ne répond pas sur `/.well-known/acme-challenge/`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:563
msgid ""
"`curl http://<your-domain>/.well-known/acme-challenge/test` doit ne pas "
"rediriger en 301"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:564
msgid "Login boucle sur `/login` malgré HTTPS"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:564
msgid "`grep COOKIE_SECURE /opt/gitrust/.env`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:564
msgid ""
"Doit être `true` ; vérifier que Nginx forward bien `X-Forwarded-Proto https`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:565
msgid "Push SSH `Connection closed`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:565
msgid "`journalctl -u gitrust \\| grep ssh`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:565
msgid ""
"Vérifier que gitrust écoute bien `127.0.0.1:2222` et que nginx stream forward"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:566
msgid "`nginx -t` : `unknown directive \"stream\"`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:566
msgid "Module non chargé"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:566
msgid "`sudo apt install libnginx-mod-stream` puis `systemctl restart nginx`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:567
msgid "Mixed content HTTPS"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:567
msgid "Templates qui hardcodent `http://`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:567
msgid "Vérifier `EMAIL_BASE_URL=https://...` et headers `X-Forwarded-Proto`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:568
msgid "Push gros repo timeout"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:568
msgid "Logs nginx `client intended to send too large body`"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:568
msgid "Augmenter `client_max_body_size 2G` (déjà fait pour `.git/`)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:572
msgid "Récapitulatif des ports"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:574
msgid "Port"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:574
msgid "Process"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:574
msgid "Exposition"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:574
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:57
#: src/administration_manual/how-to/integrer-dependency-track.md:65
#: src/administration_manual/reference/parametres-dynamiques.md:28
#: src/developer_manual/how-to/importer-depot-externe-code.md:9
#: src/developer_manual/reference/architecture-crates.md:59
#: src/developer_manual/reference/architecture-crates.md:74
#: src/developer_manual/reference/architecture-crates.md:90
#: src/developer_manual/reference/architecture-crates.md:142
#: src/developer_manual/reference/architecture-crates.md:235
#: src/developer_manual/reference/regles-qa-anssi.md:20
msgid "Rôle"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:576
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:98
msgid "22"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:576
msgid "nginx (stream)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:576
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:577
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:578
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:579
msgid "Public"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:576
msgid "SSH Git → forward vers :2222"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:577
msgid "80"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:577
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:578
msgid "nginx"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:577
msgid "ACME challenge + redirect HTTPS"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:578
msgid "443"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:578
msgid "HTTPS → forward vers :4000"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:579
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:508
msgid "2022"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:579
msgid "sshd système"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:579
msgid "Admin SSH (à restreindre par firewall si possible)"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:580
msgid "2222"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:580
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:581
msgid "gitrust"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:580
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:581
#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:582
msgid "Loopback"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:580
msgid "Backend SSH russh"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:581
msgid "4000"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:581
msgid "Backend HTTP axum"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:582
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:519
msgid "5432"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:582
msgid "docker-proxy"
msgstr ""

#: src/administration_manual/tutorials/04-mise-en-production-192-168.md:582
msgid "PostgreSQL"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:1
msgid "Configurer le runner CI distant"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:3
msgid ""
"Guide d'usage du script qui provisionne une machine distante pour exécuter "
"les pipelines CI/CD de gitrust via SSH + rsync + Dagger."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:7
msgid "1. Rôle du script"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:9
msgid ""
"`deployment/setup-remote-ci.sh` (disponible dans le dépôt source gitrust) "
"prépare **un serveur de build distant** utilisé par le worker CI de gitrust. "
"Il automatise 6 étapes :"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:11
msgid "Vérifie la connectivité SSH vers le runner"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:12
msgid ""
"Installe **Docker** (`curl https://get.docker.com | sh`) s'il est absent"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:13
msgid ""
"Installe **Dagger CLI** (`curl https://dl.dagger.io/dagger/install.sh | sh`) "
"s'il est absent"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:14
msgid "Crée le répertoire de travail distant (`CI_REMOTE_PATH`)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:15
msgid ""
"Synchronise le module `deployment/ci-engine/` (mode CI Easy) via `rsync -az "
"--delete`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:16
msgid "Smoke test : affiche `docker --version` et `dagger version`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:18
msgid ""
"Le script est **idempotent** : rejoue sans dommage, skip ce qui existe déjà."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:22
msgid "2. Quand l'utiliser"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:24
msgid "Scénario"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:24
msgid "Besoin de `setup-remote-ci.sh` ?"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:26
msgid ""
"Dev local, CI sur la même machine que gitrust (`CI_REMOTE_HOST=localhost`)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:26
msgid ""
"**Non** — Docker et Dagger déjà installés localement, le `ci-engine/` est lu "
"depuis `deployment/ci-engine/` directement"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:27
msgid "Prod on-premise, un seul serveur (gitrust + CI colocalisés)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:27
msgid ""
"**Non** — idem, un simple `curl get.docker.com \\| sh` suffit sur le serveur "
"gitrust"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:28
msgid "Prod avec **runner CI dédié** (machine séparée)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:28
msgid "**OUI** — c'est le cas cible de ce script"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:29
msgid "Prod avec plusieurs instances gitrust partageant un runner"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:29
msgid ""
"**OUI** — le runner est provisionné une fois, chaque instance pointe dessus"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:30
msgid "CI dans Kubernetes / Nomad / runner managé cloud"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:30
msgid "**Non** — ce script est pensé pour une VM Debian/Ubuntu classique"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:34
msgid "3. Architecture cible"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:49
msgid ""
"Le worker CI de gitrust (tâche Tokio dans le binaire principal) ne fait "
"**pas tourner** Docker localement — il délègue au runner via SSH. Cela "
"permet d'isoler les workloads CPU/RAM gourmands (builds Rust, Node, Docker) "
"du process web de gitrust."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:53
msgid "4. Pré-requis"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:55
msgid "Sur la machine d'exécution (là où on lance le script)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:57
#: src/administration_manual/how-to/integrer-dependency-track.md:65
#: src/developer_manual/reference/regles-qa-anssi.md:20
msgid "Outil"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:59
msgid "`bash` ≥ 4"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:59
msgid "Interpréteur"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:60
msgid "`ssh`, `rsync`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:60
msgid "Transport et synchro"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:61
msgid "`ssh-agent` chargé **ou** `CI_REMOTE_SSH_KEY` défini"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:61
msgid "Auth SSH sans mot de passe interactif (`BatchMode=yes`)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:62
msgid "Fichier `.env` avec les variables CI_REMOTE\\_\\*"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:62
msgid "Config (voir section 5)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:64
msgid "Sur le runner distant"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:66
msgid "Pourquoi"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:68
msgid "OS Linux récent (Debian 12+, Ubuntu 22.04+)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:68
msgid "Docker install script compatible"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:69
msgid "User avec `sudo` passwordless **ou** droits `docker`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:69
msgid "`get.docker.com` fait `sudo` en interne"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:70
msgid "Clé SSH publique du user local dans `~/.ssh/authorized_keys`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:70
msgid "Auth SSH non-interactive"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:71
msgid "Réseau sortant autorisé vers `get.docker.com` et `dl.dagger.io`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:71
msgid "Installation des binaires"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:72
msgid "Au minimum ~5 Go libres dans `CI_REMOTE_PATH`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:72
msgid "Images Docker + workspaces"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:76
msgid "5. Variables d'environnement attendues (le `.env`)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:78
msgid ""
"Le script **source un fichier `.env`** dont le chemin est passé en argument, "
"ou par défaut `../.env` (relatif au script, donc `<racine_projet>/.env`)."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:80
msgid "Tableau des variables"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:82
msgid "Obligatoire"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:82
#: src/administration_manual/reference/parametres-dynamiques.md:106
msgid "Défaut"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:82
#: src/administration_manual/reference/parametres-dynamiques.md:106
#: src/developer_manual/how-to/lancer-tests-unitaires.md:106
#: src/developer_manual/how-to/lancer-tests-e2e.md:89
#: src/developer_manual/how-to/lancer-tests-e2e.md:103
#: src/developer_manual/how-to/lancer-tests-e2e.md:114
#: src/developer_manual/how-to/lancer-tests-e2e.md:125
msgid "Description"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:84
msgid "`CI_REMOTE_HOST`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:84
msgid "**OUI**"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:84
msgid "Hostname ou IP du runner (ex: `ci-runner.internal`)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:85
msgid "`CI_REMOTE_USER`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:85
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:86
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:87
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:88
msgid "non"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:85
msgid "`$(whoami)` (user courant)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:85
msgid "Compte SSH sur le runner"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:86
msgid "`CI_REMOTE_SSH_PORT`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:86
msgid "`22`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:86
msgid "Port SSH du runner"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:87
msgid "`CI_REMOTE_PATH`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:87
msgid "`/opt/gitrust-ci`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:87
msgid "Répertoire de travail distant (créé par le script)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:88
msgid "`CI_REMOTE_SSH_KEY`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:88
msgid "— (ssh-agent)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:88
msgid "Chemin d'une clé privée SSH spécifique"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:90
msgid ""
"Ces variables sont les **mêmes** que celles lues par gitrust au runtime. "
"Centraliser dans `.env` évite les divergences entre le provisionnement et le "
"runtime."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:92
msgid "Exemple minimal de `.env` (runner dédié)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:95
msgid "# --- CI runner distant ---\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:96
msgid "<ci-runner-ip>"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:97
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:114
msgid "ci-runner"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:99
#: src/administration_manual/how-to/configurer-ci-runner-remote.md:115
msgid "/opt/gitrust-ci"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:100
msgid "/home/gitrust/.ssh/ci_runner_ed25519"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:103
msgid "Exemple `.env` complet coexistant avec config gitrust"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:106
msgid "postgres://..."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:107
msgid "..."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:107
msgid "# ... (voir .env.example pour le reste)\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:109
msgid "# --- CI/CD (lu par gitrust ET par setup-remote-ci.sh) ---\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:111
msgid "true"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:112
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:511
msgid "4"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:113
msgid "ci-runner.internal"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:116
msgid "/opt/gitrust/data/ci_runner_key"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:119
msgid "Cas « runner local » (pas besoin du script)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:122
msgid "localhost"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:122
msgid "# Les autres CI_REMOTE_* sont ignorés\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:126
msgid ""
"Dans ce cas, installer Docker et Dagger directement sur la machine gitrust, "
"copier `deployment/ci-engine/` vers `CI_ENGINE_PATH` (défaut `/opt/gitrust/"
"ci-engine`) et passer à la suite. **Ne pas exécuter `setup-remote-ci.sh`** "
"avec `CI_REMOTE_HOST=localhost`."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:130
msgid "6. Usage"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:132
msgid "Depuis la racine du projet (par défaut)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:136
msgid "# .env a la racine (défaut) :\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:141
msgid "Avec un `.env` explicite"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:144
msgid "# Utile si vous avez .env.production, .env.staging, etc.\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:149
msgid "Sortie attendue"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:184
msgid "7. Ce qui se retrouve sur le runner"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:186
msgid "Après exécution réussie :"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:195
msgid "Plus, installés globalement :"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:196
msgid "`/usr/bin/docker` (ou équivalent) + socket `/var/run/docker.sock`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:197
msgid "`/usr/local/bin/dagger`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:199
msgid ""
"Les **workspaces de pipelines** (checkouts temporaires) sont créés par le "
"worker CI de gitrust au moment de l'exécution sous `CI_WORKSPACE_PATH` "
"(défaut `/tmp/gitrust-ci`) — **pas par ce script**."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:203
msgid "8. Vérifications post-setup"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:205
msgid "Depuis la machine gitrust"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:208
msgid "# Source le .env\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:210
msgid "# 1. SSH direct (doit passer sans prompt)\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:222
msgid "Pipeline de test via gitrust"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:224
msgid "Pousser un dépôt avec un `.gitrust-ci.yml` minimal :"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:227
msgid ""
"# .gitrust-ci.yml\n"
"version"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:228
msgid "pipeline"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:230
msgid "name"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:230
msgid "smoke"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:231
msgid "image"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:231
msgid "alpine:3"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:232
msgid "run"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:232
msgid "echo \"CI runner OK\""
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:235
msgid ""
"Puis dans l'UI gitrust : onglet `Pipelines` → la pipeline doit passer au "
"statut `success`."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:239
msgid "9. Mise à jour après modification du `ci-engine/`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:241
msgid ""
"Le `ci-engine/` synchronisé n'est pas « live-linké » : rejouer le script "
"après modification côté source."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:244
msgid "# Modifier deployment/ci-engine/profiles/*.py ou similaire\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:245
msgid ""
"# Les étapes 2-3 sont skip (déjà installés), seule l'étape 5 refait le "
"rsync\n"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:249
msgid ""
"`rsync -az --delete` **supprime** les fichiers côté runner qui n'existent "
"plus localement — garantit la cohérence."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:253
msgid "10. Dépannage"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:257
msgid "`ERREUR: fichier .env introuvable`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:257
msgid "`.env` absent ou chemin incorrect"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:257
msgid ""
"`cp .env.example .env && $EDITOR .env` ou passer le chemin : `./setup-remote-"
"ci.sh /path/to/.env`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:258
msgid "`ERREUR: CI_REMOTE_HOST non défini`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:258
msgid "Variable commentée ou absente"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:258
msgid "Décommenter `CI_REMOTE_HOST=...` dans le `.env`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:259
msgid "`ERREUR: impossible de se connecter`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:259
msgid "SSH bloqué, mauvais user, clé non autorisée"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:259
msgid ""
"Tester manuellement : `ssh -v -p X user@host` ; vérifier `~/.ssh/"
"authorized_keys` sur le runner"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:260
msgid "`Permission denied (publickey)`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:260
msgid "`BatchMode=yes` interdit les prompts, clé non chargée"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:260
msgid ""
"`ssh-add ~/.ssh/ci_runner_ed25519` ou définir `CI_REMOTE_SSH_KEY=/path/to/"
"key`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:261
msgid "`sudo: a password is required` pendant l'install Docker"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:261
msgid "User sans `NOPASSWD` sudo"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:261
msgid ""
"Ajouter le user au `sudoers` : `ci-runner ALL=(ALL) NOPASSWD:ALL` (runner "
"uniquement)"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:262
msgid "`curl: (7) Failed to connect to get.docker.com`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:262
msgid "Réseau sortant du runner bloqué"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:262
msgid ""
"Whitelist `get.docker.com` et `dl.dagger.io`, ou pré-installer Docker + "
"Dagger manuellement"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:263
msgid "`ATTENTION: ... ci-engine introuvable`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:263
msgid "Lancé hors du repo gitrust"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:263
msgid "`cd` dans la racine du projet avant de lancer"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:264
msgid "Pipeline reste `queued` indéfiniment"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:264
msgid "Worker CI ne trouve pas le runner"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:264
msgid ""
"Vérifier `CI_EXECUTION_MODE=remote` dans `.env` gitrust + logs : `journalctl "
"-u gitrust \\| grep -i 'ci\\|dagger'`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:265
msgid "`dagger: command not found` au smoke test"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:265
msgid "`$PATH` du user SSH ne contient pas `/usr/local/bin`"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:265
msgid ""
"`echo 'export PATH=$PATH:/usr/local/bin' >> ~/.bashrc` sur le runner, ou "
"`CI_DAGGER_BIN=/usr/local/bin/dagger` côté gitrust"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:269
msgid "11. Sécurité"
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:271
msgid ""
"Le runner CI exécute du **code arbitraire** venant des dépôts hébergés. **Ne "
"jamais** le colocaliser avec des secrets sensibles (PG prod, clés de prod)."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:272
msgid ""
"Isoler réseau : bloquer l'accès sortant du runner vers le LAN privé (seul "
"l'accès Internet pour `docker pull` est nécessaire)."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:273
msgid ""
"Limiter `sudo NOPASSWD` au strict minimum sur le runner (idéalement : juste "
"pour les commandes `docker` et `apt`)."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:274
msgid ""
"Rotation régulière de la clé SSH `CI_REMOTE_SSH_KEY`. La révoquer dans `~/."
"ssh/authorized_keys` côté runner en cas de suspicion."
msgstr ""

#: src/administration_manual/how-to/configurer-ci-runner-remote.md:275
msgid ""
"Le runner ne doit **pas** pouvoir se connecter en SSH à la machine gitrust "
"(unidirectionnel)."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:1
msgid "Intégrer la CI et Dependency-Track"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:3
msgid ""
"Ce document explique comment activer et configurer les deux fonctionnalités "
"de qualité/sécurité de gitrust :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:5
msgid ""
"**La CI intégrée** (Dagger) qui exécute les builds/tests/lints à chaque push."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:6
msgid ""
"**Le dependency tracker** (Syft + Dependency-Track) qui scanne les "
"composants du code à chaque push et détecte les vulnérabilités connues."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:8
msgid ""
"Ces deux systèmes sont **indépendants** : on peut activer l'un sans l'autre."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:12
msgid "1. Architecture générale"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:51
msgid "Trois composants fonctionnent en parallèle :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:53
msgid ""
"**CiWorker** : tâche Tokio qui consomme des `CiTask` depuis un channel "
"`mpsc`, limitée par un `Semaphore` à `CI_MAX_CONCURRENT` pipelines "
"simultanés."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:54
msgid ""
"**SbomService** : exécuté dans un `tokio::spawn` après chaque push, "
"totalement découplé du CI."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:55
msgid ""
"**Serveur de build** : machine distante (ou `localhost`) qui exécute Docker "
"+ Dagger. Gitrust y envoie le workspace par rsync et lance Dagger par SSH."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:59
msgid "2. Mettre en place la CI"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:61
msgid "2.1 Pré-requis serveur de build"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:63
msgid ""
"Le serveur de build peut être **la même machine que Gitrust** "
"(`CI_REMOTE_HOST=localhost`) ou une machine dédiée. Il doit disposer de :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:67
msgid "Docker ou Podman"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:67
msgid "Containers Dagger"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:68
msgid "Dagger CLI"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:68
msgid "Moteur d'exécution"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:69
msgid "SSH (accès sortant depuis Gitrust)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:69
msgid "Transport"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:70
msgid "rsync"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:70
msgid "Copie du workspace"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:71
msgid "git, tar"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:71
msgid "Extraction du tree du commit"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:73
msgid "Installation automatique recommandée :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:76
msgid ""
"# Depuis la machine Gitrust (l'utilisateur doit pouvoir SSH vers le "
"builder)\n"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:80
msgid "Le script exécute :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:82
msgid "Vérification de la connectivité SSH"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:83
msgid "Installation de Docker si absent"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:84
msgid "Installation de Dagger CLI si absent"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:85
msgid "Création du répertoire de travail distant"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:86
msgid "Synchronisation du `ci-engine`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:87
msgid "Smoke test (versions)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:89
msgid "2.2 Configuration Gitrust (fichier .env)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:91
msgid "Ajouter au `.env` de Gitrust :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:93
msgid ""
"```env\n"
"# Activer globalement le CI\n"
"CI_ENABLED=true\n"
"\n"
"# Chemin du ci-engine sur le serveur de build\n"
"CI_ENGINE_PATH=/opt/gitrust-ci/ci-engine\n"
"\n"
"# Limite de parallélisme\n"
"CI_MAX_CONCURRENT=4\n"
"CI_DEFAULT_TIMEOUT=3600\n"
"CI_WORKSPACE_PATH=/tmp/gitrust-ci\n"
"\n"
"# Serveur de build (mettre localhost pour \"même machine\")\n"
"CI_REMOTE_HOST=builder.example.com\n"
"CI_REMOTE_USER=ci-runner\n"
"CI_REMOTE_PATH=/opt/gitrust-ci\n"
"CI_REMOTE_SSH_PORT=22\n"
"# CI_REMOTE_SSH_KEY=/home/gitrust/.ssh/id_ed25519   # si pas ssh-agent\n"
"```"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:113
msgid ""
"Redémarrer Gitrust : `systemctl restart gitrust` (ou `cargo run --release`)."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:115
msgid "2.3 Activer la CI sur un dépôt"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:117
msgid "Dans l'interface web : aller sur le dépôt → **Settings** → **CI**."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:119
msgid "Cocher **CI enabled** (requis — par défaut `false`)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:120
msgid "Cocher **Trigger on push** (active l'exécution à chaque push)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:121
msgid ""
"Optionnel : **Auto-cancel** (annule les pipelines en cours quand un nouveau "
"démarre)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:122
msgid "Optionnel : **Allowed branches** (ex. `main,develop` — vide = toutes)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:124
msgid "2.4 Choisir le mode : Easy ou Power"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:136
msgid "Mode Easy (recommandé pour commencer)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:138
msgid "Créer `.gitrust-ci.yml` à la racine du dépôt :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:141
msgid ""
"# Raccourci : charge un profil pré-configuré (rust | python | node)\n"
"language"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:142
#: src/developer_manual/tutorials/01-getting-started.md:332
msgid "rust"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:143
#: src/developer_manual/tutorials/01-getting-started.md:333
msgid "build"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:145
#: src/administration_manual/how-to/integrer-dependency-track.md:152
#: src/developer_manual/tutorials/01-getting-started.md:335
#: src/developer_manual/tutorials/01-getting-started.md:338
msgid "command"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:145
#: src/developer_manual/tutorials/01-getting-started.md:335
msgid "\"cargo build --release\""
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:146
msgid "checks"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:148
msgid "lint"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:148
msgid "\"cargo clippy -- -D warnings\""
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:149
msgid "format"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:149
msgid "\"cargo fmt -- --check\""
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:150
#: src/developer_manual/tutorials/01-getting-started.md:336
msgid "tests"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:152
msgid "\"cargo test --release\""
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:155
msgid ""
"Les profils disponibles se trouvent dans `deployment/ci-engine/profiles/` "
"(rust.yaml, python.yaml, node.yaml) dans le dépôt source."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:157
msgid "Mode Power"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:159
msgid ""
"Pour les utilisateurs avancés, créer un module Dagger complet dans `.dagger/"
"` :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:168
msgid "La fonction `ci` du module est appelée directement :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:174
msgid ""
"Avantage : accès au Daggerverse, composition, tests de pipeline. Voir la "
"[documentation Dagger](https://docs.dagger.io/)."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:176
msgid "2.5 Suivi d'un pipeline"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:178
msgid ""
"Après un `git push`, une entrée apparaît dans l'onglet **CI** du dépôt :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:192
msgid ""
"Les logs stdout/stderr sont streamés ligne par ligne dans la table `ci_logs` "
"et visibles en direct dans l'UI. En cas d'échec, une notification est "
"envoyée au propriétaire du dépôt."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:196
msgid "3. Mettre en place le Dependency Tracker"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:198
msgid ""
"Cette partie est totalement indépendante de la CI. Elle scanne le code "
"poussé et produit un SBOM CycloneDX, puis (optionnellement) l'envoie à "
"Dependency-Track pour une analyse de vulnérabilités."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:200
msgid "3.1 Installer Syft"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:202
msgid ""
"Sur la machine Gitrust (le scan se fait localement, pas sur le builder) :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:205
msgid "# Installation officielle\n"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:213
msgid "Dans `.env` :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:220
msgid ""
"À ce stade : à chaque push, un SBOM CycloneDX est généré et stocké (sans "
"upload externe). Visible dans l'onglet **Security** du dépôt : nombre de "
"composants, sha256 du BOM."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:222
msgid "3.2 Déployer Dependency-Track"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:224
msgid ""
"Dependency-Track est une application Java qui stocke les SBOM et corrèle "
"avec les bases CVE/OSV/NVD. Déploiement Docker recommandé :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:233
msgid ""
"L'API est disponible sur `http://localhost:8081` et l'UI sur `http://"
"localhost:8080`. Login initial : `admin` / `admin` (à changer immédiatement)."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:236
msgid "3.3 Créer une clé API"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:238
msgid ""
"Dans Dependency-Track → **Administration** → **Access Management** → "
"**Teams** :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:240
msgid "Créer (ou réutiliser) une équipe `gitrust`."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:241
msgid "Lui attribuer les permissions :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:242
msgid "`BOM_UPLOAD`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:243
msgid "`PROJECT_CREATION_UPLOAD`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:244
msgid "`VIEW_PORTFOLIO`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:245
msgid "`VIEW_VULNERABILITY`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:246
msgid "Générer une API key et la copier."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:248
msgid "3.4 Configurer Gitrust"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:250
msgid "Ajouter au `.env` :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:252
msgid ""
"```env\n"
"CI_DTRACK_ENABLED=true\n"
"CI_DTRACK_URL=http://localhost:8081\n"
"CI_DTRACK_API_KEY=odt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
"```"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:258
msgid "Redémarrer Gitrust. À chaque push :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:286
msgid "3.5 Lire les résultats"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:288
msgid "Onglet **Security** du dépôt → encart SBOM :"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:290
msgid "Nombre de composants détectés"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:291
msgid "Compteurs par sévérité : Critical / High / Medium / Low"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:292
msgid "Lien direct vers le projet dans Dependency-Track (si l'UUID est résolu)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:293
msgid "Hash sha256 du BOM (traçabilité)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:295
msgid ""
"Si Dependency-Track met plus de 30s à analyser, le status reste `processing` "
"— un sweeper ultérieur ira rechercher les findings."
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:299
msgid "4. Débogage"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:301
msgid "Problèmes CI courants"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:303
#: src/administration_manual/how-to/integrer-dependency-track.md:312
msgid "Vérifier"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:305
msgid "Pipeline reste `pending`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:305
msgid "Worker non démarré, ou channel saturé"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:305
msgid "Logs `CI worker started`, `CI_MAX_CONCURRENT`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:306
msgid "`Échec rsync vers le serveur de build`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:306
msgid "SSH bloqué, clé absente"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:306
msgid ""
"`ssh -p ${CI_REMOTE_SSH_PORT} ${CI_REMOTE_USER}@${CI_REMOTE_HOST}` manuel"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:307
msgid "`dagger: command not found`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:307
msgid "Dagger non installé sur le builder"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:307
msgid "Relancer `setup-remote-ci.sh`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:308
msgid "Status `Cancelled` inattendu"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:308
msgid "Timeout (`CI_DEFAULT_TIMEOUT`) ou auto-cancel"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:308
msgid "Augmenter le timeout, vérifier pipelines concurrents"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:310
msgid "Problèmes SBOM courants"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:314
msgid "`SBOM generation disabled`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:314
msgid "`CI_SBOM_ENABLED=false`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:314
#: src/administration_manual/reference/parametres-dynamiques.md:31
msgid "`.env`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:315
msgid "`syft spawn failed`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:315
msgid "Binaire introuvable"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:315
msgid "`which syft`, `CI_SYFT_BIN`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:316
msgid "`invalid commit sha`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:316
msgid "SHA non hex 40 chars"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:316
msgid "Rare, signale un bug"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:317
msgid "`Dtrack upload 401`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:317
msgid "API key invalide ou permissions manquantes"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:317
msgid "Régénérer, vérifier les 4 permissions"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:318
msgid "Status `processing` indéfiniment"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:318
msgid "Dtrack surchargé, analyse lente"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:318
msgid "Attendre, ou relancer un push"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:320
msgid "Logs utiles"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:323
msgid "# Logs Gitrust (systemd)\n"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:324
msgid "\"CI|SBOM|sbom|pipeline\""
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:325
msgid "# Vérifier un pipeline en DB\n"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:327
msgid ""
"\"SELECT id, status, commit_sha, created_at FROM ci_pipelines ORDER BY "
"created_at DESC LIMIT 10;\""
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:328
msgid "# Vérifier un SBOM\n"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:330
msgid ""
"\"SELECT commit_sha, status, components_count, critical_count, high_count "
"FROM sbom_reports ORDER BY created_at DESC LIMIT 10;\""
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:335
msgid "5. Checklist récapitulative"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:337
msgid "**CI :**"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:338
msgid ""
"Docker + Dagger installés sur le serveur de build (`setup-remote-ci.sh`)"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:339
msgid "`CI_ENABLED=true` et `CI_REMOTE_*` dans `.env`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:340
#: src/administration_manual/how-to/integrer-dependency-track.md:350
msgid "Gitrust redémarré"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:341
msgid "CI activée dans Settings → CI pour chaque dépôt"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:342
msgid "Fichier `.gitrust-ci.yml` (Easy) ou `.dagger/` (Power) commité"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:343
msgid "Push → pipeline visible dans l'onglet CI"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:345
msgid "**Dependency Tracker :**"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:346
msgid "Syft installé sur la machine Gitrust"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:347
msgid "`CI_SBOM_ENABLED=true` dans `.env`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:348
msgid ""
"(Optionnel) Dependency-Track déployé + API key créée avec les 4 permissions"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:349
msgid ""
"(Optionnel) `CI_DTRACK_ENABLED=true`, `CI_DTRACK_URL`, `CI_DTRACK_API_KEY` "
"dans `.env`"
msgstr ""

#: src/administration_manual/how-to/integrer-dependency-track.md:351
msgid "Push → SBOM visible dans l'onglet Security"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:1
msgid "Durcir l'instance avec Fail2ban"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:3
msgid "Configuration complète pour protéger un déploiement gitrust exposant :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:5
msgid "**sshd système** sur `:2022` (admin)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:6
msgid ""
"**Nginx** en reverse proxy HTTPS `:443` + redirect `:80` + `stream :22 "
"→ :2222`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:7
msgid "**Gitrust** (web `127.0.0.1:4000`, SSH russh `127.0.0.1:2222`)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:8
msgid "**Dagger** CI runner (local, pas d'exposition réseau directe)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:9
msgid "**Dependency-Track** API `:8081` + UI `:8080` (si exposés)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:10
msgid "**PostgreSQL** `127.0.0.1:5432` (défensif au cas où le bind fuit)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:14
msgid "1. Installation"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:22
msgid ""
"Vérifier que `ufw` est actif (fournit `banaction = ufw` dans la config) :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:30
msgid "2. Fichier principal `/etc/fail2ban/jail.local`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:32
msgid "À placer via :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:34
msgid ""
"<<'EOF'\n"
"[Le contenu ci-dessous]\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:223
msgid "3. Filtres personnalisés"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:225
msgid "À placer dans `/etc/fail2ban/filter.d/` (un fichier par jail custom)."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:227
msgid "3.1 `gitrust-login.conf`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:230
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"# POST sur /login ou endpoints JWT avec code 4xx (401/403/422/429)\n"
"failregex = ^<HOST> .* \"POST /(login|api/v1/auth/login|api/v1/auth/refresh|"
"api/v1/auth/2fa)[^\"]*\" (401|403|422|429) .*$\n"
"ignoreregex =\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:238
msgid "3.2 `gitrust-api-abuse.conf`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:241
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"# Abus API : 401/403 répétés sur /api/v1/* (hors auth déjà couvert par "
"gitrust-login)\n"
"failregex = ^<HOST> .* \"(GET|POST|PUT|DELETE|PATCH) /api/v1/(?!auth/)"
"[^\"]*\" (401|403) .*$\n"
"ignoreregex =\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:249
msgid "3.3 `gitrust-ssh.conf`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:252
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"# russh / gitrust-ssh : échecs d'authentification\n"
"# Regex à raffiner après observation des logs réels via :\n"
"#   sudo fail2ban-regex <(journalctl -u gitrust --no-pager -n 2000) \\\n"
"#                       /etc/fail2ban/filter.d/gitrust-ssh.conf\n"
"failregex = ^.*ssh.*auth(entication)? (failed|failure).*from <HOST>.*$\n"
"            ^.*[Rr]ejected.*(public[_ ]?key|password).*from <HOST>.*$\n"
"            ^.*no matching (ssh|public) key.*from <HOST>.*$\n"
"            ^.*unknown user.*from <HOST>.*$\n"
"            ^.*gitrust.*auth.*refused.*<HOST>.*$\n"
"ignoreregex =\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:267
msgid "3.4 `gitrust-import.conf`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:270
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"# Import worker : tokens OAuth/GitHub invalides sur clone de dépôts "
"externes\n"
"failregex = ^.*import.*authentication failed.*from <HOST>.*$\n"
"            ^.*import.*invalid (token|credentials).*from <HOST>.*$\n"
"            ^.*import.*clone failed.*401.*from <HOST>.*$\n"
"ignoreregex =\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:280
msgid "3.5 `dtrack-login.conf` (si DTrack exposé)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:283
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"# Dependency-Track : brute force du POST /api/v1/user/login\n"
"failregex = ^<HOST> .* \"POST /api/v1/user/login[^\"]*\" (401|403) .*$\n"
"            ^<HOST> .* \"POST /api/v1/user/forceChangePassword[^\"]*\" (401|"
"403) .*$\n"
"ignoreregex =\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:292
msgid "3.6 `dtrack-api.conf` (si DTrack exposé)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:295
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"# Dependency-Track API : abus de clé API ou requêtes non authentifiées\n"
"failregex = ^<HOST> .* \"[^\"]+ /api/v1/[^\"]*\" 401 .*$\n"
"            ^<HOST> .* \"[^\"]+ /api/v1/[^\"]*\" 403 .*$\n"
"ignoreregex =\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:304
msgid "3.7 `postgresql.conf` (créer si absent)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:308
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"failregex = ^.*authentication failed for user.*host=<HOST>.*$\n"
"            ^.*FATAL:.*password authentication failed.*<HOST>.*$\n"
"            ^.*no pg_hba\\.conf entry for host \"<HOST>\".*$\n"
"ignoreregex =\n"
"EOF\n"
"fi\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:318
msgid "3.8 `nginx-limit-req.conf` (créer si absent sur votre distro)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:322
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"failregex = ^.*limiting requests, excess: .* by zone .*, client: <HOST>.*$\n"
"ignoreregex =\n"
"EOF\n"
"fi\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:330
msgid "3.9 `nginx-badbots.conf` — OBLIGATOIRE (pas fourni par Debian/Ubuntu)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:332
msgid ""
"Le paquet `fail2ban` Debian/Ubuntu fournit `apache-badbots.conf` mais PAS "
"`nginx-badbots.conf`. Sans ce filter, `fail2ban-client reload` affiche :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:338
msgid ""
"Le filter ci-dessous réutilise la liste de bad user-agents de `apache-"
"badbots` avec un `failregex` adapté au format `combined` de nginx :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:341
msgid ""
"<<'EOF'\n"
"[Definition]\n"
"badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\\.02|sogou music "
"spider\n"
"badbots = Atomic_Email_Hunter/4\\.0|atSpider/1\\.0|autoemailspider|"
"bwh3_user_agent|China Local Browse 2\\.6|ContactBot/0\\.2|ContentSmartz|"
"DataCha0s/2\\.0|DBrowse 1\\.4b|DBrowse 1\\.4d|Demo Bot DOT 16b|Demo Bot Z "
"16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\\.4b|Educate "
"Search VxB|EmailSiphon|EmailSpider|EmailWolf 1\\.00|ExtractorPro|Franklin "
"Locator 1\\.8|Full Web Bot 0416B|Guestbook Auto Submitter|ISC Systems iRc "
"Search 2\\.1|LMQueueBot/0\\.2|LWP\\:\\:Simple/5\\.803|Microsoft URL Control "
"- 6\\.00\\.8xxx|Missigua Locator 1\\.9|Mozilla/4\\.0 efp@gmx\\.net|"
"Nsauditor/1\\.x|PBrowse 1\\.4b|PEval 1\\.4b|Poirot|psycheclone|sogou spider|"
"sohu agent|VadixBot|WebVulnCrawl\\.unknown/1\\.0 libwww-perl/5\\.803|Wells "
"Search II|WEP Search 00\n"
"\n"
"failregex = ^<HOST> -.*\"(GET|POST|HEAD).*HTTP.*\"(?:%(badbots)s|"
"%(badbotscustom)s)\"$\n"
"ignoreregex =\n"
"\n"
"datepattern = ^[^\\[]*\\[({DATE})\n"
"              {^LN-BEG}\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:354
msgid ""
"**Alternative** : si vous ne voulez pas maintenir la liste, simplement "
"désactiver le jail (`enabled = false` dans le `[nginx-badbots]`) — la "
"combinaison `nginx-botsearch` + `nginx-limit-req` + `gitrust-api-abuse` "
"couvre déjà l'essentiel."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:358
msgid "4. Rate limiting côté Nginx (requis par `nginx-limit-req`)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:360
msgid "4.1 Déclarer les zones globales"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:363
msgid ""
"<<'EOF'\n"
"# Zones de rate limiting gitrust\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:365
msgid ""
"limit_req_zone $binary_remote_addr zone=gitrust_api:10m   rate=10r/s;\n"
"limit_req_zone $binary_remote_addr zone=gitrust_git:10m   rate=30r/s;\n"
"EOF\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:371
msgid "4.2 Ajouter les `location` dans `/etc/nginx/sites-available/gitrust`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:373
msgid ""
"Dans le bloc `server { listen 443 ssl; ... }`, **avant** `location /` "
"finale :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:375
msgid ""
"```nginx\n"
"# Protection brute force login (1 req/s par IP, burst 5)\n"
"location ~ ^/(login|api/v1/auth/) {\n"
"    limit_req zone=gitrust_login burst=5 nodelay;\n"
"    proxy_pass http://gitrust_backend;\n"
"    proxy_set_header Host              $host;\n"
"    proxy_set_header X-Real-IP         $remote_addr;\n"
"    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;\n"
"    proxy_set_header X-Forwarded-Proto $scheme;\n"
"}\n"
"\n"
"# Protection API (10 req/s par IP, burst 20)\n"
"location ^~ /api/v1/ {\n"
"    limit_req zone=gitrust_api burst=20 nodelay;\n"
"    proxy_pass http://gitrust_backend;\n"
"    proxy_set_header Host              $host;\n"
"    proxy_set_header X-Real-IP         $remote_addr;\n"
"    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;\n"
"    proxy_set_header X-Forwarded-Proto $scheme;\n"
"}\n"
"\n"
"# Protection Git smart HTTP (30 req/s — clone/push légitime peut être "
"verbeux)\n"
"location ~ ^/[^/]+/[^/]+\\.git/ {\n"
"    limit_req zone=gitrust_git burst=50 nodelay;\n"
"    proxy_pass http://gitrust_backend;\n"
"    proxy_http_version 1.1;\n"
"    proxy_set_header Host              $host;\n"
"    proxy_set_header X-Real-IP         $remote_addr;\n"
"    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;\n"
"    proxy_set_header X-Forwarded-Proto $scheme;\n"
"    proxy_buffering off;\n"
"    proxy_request_buffering off;\n"
"    client_max_body_size 2G;\n"
"}\n"
"```"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:411
msgid "4.3 Reload"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:419
msgid "5. Démarrage et validation"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:423
msgid "# Liste des jails actifs\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:427
msgid "#   gitrust-login, gitrust-api-abuse, gitrust-ssh, gitrust-import,\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:429
msgid "#   (+ dtrack-login, dtrack-api si activées)\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:431
msgid "# Stats par jail\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:437
msgid "Valider chaque filtre custom"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:440
msgid "# 1. gitrust-login contre l'access log nginx\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:460
msgid ""
"`0 failregex found` = regex à ajuster après observation des logs réels de "
"chaque service."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:462
msgid "Test de bannissement"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:465
msgid "# Depuis un host HORS LAN (sinon ignoreip s'applique)\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:467
msgid "\"%{http_code}\\n\""
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:482
msgid "6. Monitoring"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:485
msgid "# Logs fail2ban temps réel\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:487
msgid "# Toutes les IPs bannies, tous jails confondus\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:490
msgid "# Stats détaillées d'un jail\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:492
msgid "#    Currently failed : 2\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:494
msgid "#    Currently banned : 1\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:496
msgid "#    Banned IP list   : 203.0.113.42\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:499
msgid "\"Ban \""
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:504
msgid "7. Matrice récapitulative"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:506
msgid "Jail"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:506
msgid "Port(s)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:506
msgid "Source logs"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:506
msgid "Max retry"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:506
msgid "Ban time"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:506
msgid "Surface protégée"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:508
msgid "`sshd`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:508
msgid "journald sshd"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:508
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:509
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:512
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:513
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:515
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:518
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:519
msgid "1h"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:508
msgid "SSH admin"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:509
msgid "`nginx-http-auth`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:509
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:510
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:511
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:512
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:513
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:514
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:516
msgid "80,443"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:509
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:512
msgid "nginx error"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:509
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:512
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:513
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:515
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:517
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:519
msgid "5"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:509
msgid "Basic auth (admin futur)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:510
msgid "`nginx-botsearch`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:510
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:511
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:513
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:514
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:517
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:518
msgid "nginx access"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:510
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:511
msgid "24h"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:510
msgid "Scanners WP/PHP"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:511
msgid "`nginx-badbots`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:511
msgid "User-agents malveillants"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:512
msgid "`nginx-limit-req`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:512
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:517
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:518
msgid "10"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:512
msgid "Flood global"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:513
msgid "6"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:513
msgid "`gitrust-login`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:513
msgid "Brute force login UI + API"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:514
msgid "7"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:514
msgid "`gitrust-api-abuse`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:514
msgid "30"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:514
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:517
msgid "2h"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:514
msgid "Scrapers API (tokens fuités)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:515
msgid "8"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:515
msgid "`gitrust-ssh`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:515
msgid "22,2222"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:515
#: src/administration_manual/how-to/durcir-avec-fail2ban.md:516
msgid "journald gitrust"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:515
msgid "Brute force clé SSH Git"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:516
msgid "9"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:516
msgid "`gitrust-import`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:516
msgid "30m"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:516
msgid "Brute force PAT/OAuth import"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:517
msgid "`dtrack-login`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:517
msgid "8080"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:517
msgid "Brute force UI Dep-Track"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:518
msgid "11"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:518
msgid "`dtrack-api`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:518
msgid "8081"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:518
msgid "Abus clé API Dep-Track"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:519
msgid "12"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:519
msgid "`postgresql`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:519
msgid "journald"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:519
msgid "Défense en profondeur PG"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:520
msgid "13"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:520
msgid "`recidive`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:520
msgid "all"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:520
msgid "fail2ban.log"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:520
msgid "1w"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:520
msgid "Méta-ban 3×/24h"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:522
msgid ""
"**Ordre de déclenchement typique** : brute force → jail spécifique (ban 1h) "
"→ si récidive 3x → recidive (ban 1 semaine, tous ports)."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:526
msgid "8. Notes spécifiques à la stack gitrust"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:528
msgid "8.1 Dagger (CI)"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:530
msgid ""
"Dagger s'exécute **localement** sur la machine gitrust (ou un runner distant "
"— voir `administration_manual/how-to/configurer-ci-runner-remote.md`). "
"**Aucun port réseau ouvert** → pas de jail dédié."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:532
msgid "8.2 Dependency-Track"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:534
msgid ""
"Si DTrack est déployé sur le même serveur et **exposé**, activer les jails "
"10 et 11 en mettant `enabled = true` et en pointant `logpath` vers les logs "
"nginx du vhost DTrack."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:536
msgid ""
"Si DTrack est **interne** (VPN, réseau privé), laisser `enabled = false` — "
"le firewall suffit."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:538
msgid "Config DTrack recommandée :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:539
msgid "Bind sur `127.0.0.1` via `dtrack.url.base=http://127.0.0.1:8080`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:541
msgid "8.3 PostgreSQL"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:543
msgid ""
"Le jail `postgresql` est **défensif**. PG doit rester bindé sur "
"`127.0.0.1:5432` via Docker. Vérifier :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:546
msgid "# Attendu : 127.0.0.1:5432 — PAS 0.0.0.0:5432\n"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:550
msgid "8.4 Notifications"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:552
msgid "Pour recevoir un mail à chaque ban :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:554
msgid "Installer un relay SMTP local : `sudo apt install msmtp-mta`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:555
msgid "Configurer `/etc/msmtprc` avec un compte SMTP"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:556
msgid "Décommenter dans `[DEFAULT]` :"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:562
msgid "`sudo systemctl restart fail2ban`"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:566
msgid "9. Limites et évolutions"
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:568
msgid ""
"**IPv6** : toutes les regex utilisent `<HOST>` qui matche IPv4 ET IPv6. "
"Vérifier que UFW est configuré pour v6 également."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:569
msgid ""
"**CDN/Cloudflare devant** : si un CDN est ajouté, `$remote_addr` côté Nginx "
"sera l'IP du CDN — il faut récupérer la vraie IP via `X-Forwarded-For` et "
"propager au logging Nginx. Changer `failregex` en conséquence. Sinon les "
"jails banniront le CDN."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:570
msgid ""
"**Docker/Podman** : si gitrust passe en conteneur, les logs de `gitrust."
"service` deviennent `docker.service` ou `podman.service` → mettre à jour "
"`journalmatch` dans les jails 8 et 9."
msgstr ""

#: src/administration_manual/how-to/durcir-avec-fail2ban.md:571
msgid ""
"**GeoIP** : pour bloquer des pays entiers en amont, ajouter `geo "
"$blocked_country` dans Nginx (module `ngx_http_geoip2_module`) — "
"complémentaire à fail2ban."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:3
msgid ""
"Ce document explique comment fonctionne la configuration de la plateforme, "
"les deux mécanismes en jeu, leur précédence, et les pièges à connaître."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:7
msgid "Vue d'ensemble : deux systèmes distincts"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:9
msgid "Gitrust utilise **deux systèmes de configuration** indépendants :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:11
msgid "Système"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:11
msgid "Source"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:11
msgid "Modifiable à chaud"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:11
msgid "Visible dans l'UI admin"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:13
msgid "**Configuration statique**"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:13
msgid "Fichier `.env` + variables d'environnement"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:13
msgid "Non (restart requis)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:13
#: src/administration_manual/reference/parametres-dynamiques.md:162
#: src/administration_manual/reference/parametres-dynamiques.md:176
msgid "Non"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:14
msgid "**Configuration dynamique**"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:14
msgid "Table `app_settings` (PostgreSQL)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:14
msgid "Oui (effet immédiat)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:14
msgid "Oui (`/admin/settings`)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:16
msgid ""
"Il existe un **cas hybride** pour OAuth (DB prioritaire, `.env` en fallback)."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:20
msgid "1. Configuration statique (`.env`)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:22
#: src/administration_manual/reference/parametres-dynamiques.md:74
msgid "Principe"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:24
msgid ""
"Les variables d'environnement sont chargées **une seule fois au démarrage** "
"par `dotenvy::dotenv()` et stockées dans des structs Rust immuables. Elles "
"ne sont jamais relues après le boot."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:26
msgid "Fichiers de référence"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:28
#: src/template/index.md:11 src/template/index.md:22 src/template/index.md:33
#: src/template/index.md:43 src/template/index.md:52 src/template/index.md:65
#: src/template/index.md:76 src/template/index.md:86
msgid "Fichier"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:30
msgid "`.env.example`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:30
msgid "Template documenté avec toutes les variables"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:31
msgid "Configuration locale (gitignore)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:32
msgid "`.env.production`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:32
msgid "Configuration de déploiement"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:33
msgid "`.env.test`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:33
msgid "Configuration de tests"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:35
msgid "Structs de chargement"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:37
msgid "Struct"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:37
msgid "Variables concernées"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:39
msgid "`GitrustConfig`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:39
msgid ""
"`GIT_REPOS_BASE_PATH`, `SSH_PORT`, `SSH_LISTEN_ADDR`, `SSH_HOST_KEY_PATH`, "
"`CI_*`, `IMPORT_*`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:40
msgid "`AppConfig`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:40
msgid "`APP_NAME`, `APP_THEME`, `APP_DEBUG`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:41
msgid "`AuthConfig`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:41
msgid ""
"`JWT_SECRET`, `JWT_EXPIRATION_MINUTES`, `SESSION_*`, `RATE_LIMIT_*`, "
"`COOKIE_*`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:42
msgid "`EmailConfig`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:42
msgid "`SMTP_*`, `EMAIL_*`, `IMAP_*`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:44
msgid "Comportement"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:46
msgid "Chargées dans `RustwardenApp::build()` au démarrage"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:47
msgid "Stockées dans des `Arc<Config>` partagés via l'état axum"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:48
msgid "**Modifier le `.env` sans redémarrer n'a aucun effet**"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:49
msgid "**Ces variables ne sont PAS affichées dans l'interface admin**"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:51
msgid "Liste des variables statiques (non exhaustive)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:72
msgid "2. Configuration dynamique (table `app_settings`)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:76
msgid ""
"Les réglages dynamiques sont stockés en base PostgreSQL dans la table "
"`app_settings` et lus **à chaque requête** via `AppSettingsService`. Ils "
"sont modifiables à chaud par un administrateur depuis l'interface `/admin/"
"settings`."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:78
msgid "Schéma de la table"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:91
msgid "Initialisation au démarrage"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:93
msgid ""
"Au boot, `AppSettingsService::initialize_default_settings()` crée les "
"réglages par défaut **uniquement s'ils n'existent pas encore en base** :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:98
msgid "// ... insert valeur par défaut\n"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:102
msgid ""
"**Conséquence critique** : une fois qu'un réglage existe en base (créé au "
"premier démarrage ou modifié via l'UI), il n'est **jamais écrasé** par un "
"redémarrage ultérieur."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:104
msgid "Liste des réglages dynamiques et leurs valeurs par défaut"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:106
msgid "Clé"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:108
msgid "`app_domain`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:108
msgid "`env::var(\"APP_DOMAIN\")` ou `\"localhost\"`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:108
msgid "Domaine de l'application"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:109
#: src/administration_manual/reference/parametres-dynamiques.md:186
msgid "`allow_registration`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:109
#: src/administration_manual/reference/parametres-dynamiques.md:114
#: src/administration_manual/reference/parametres-dynamiques.md:115
#: src/administration_manual/reference/parametres-dynamiques.md:116
#: src/administration_manual/reference/parametres-dynamiques.md:117
#: src/administration_manual/reference/parametres-dynamiques.md:119
#: src/administration_manual/reference/parametres-dynamiques.md:121
#: src/administration_manual/reference/parametres-dynamiques.md:123
#: src/administration_manual/reference/parametres-dynamiques.md:124
#: src/administration_manual/reference/parametres-dynamiques.md:125
#: src/administration_manual/reference/parametres-dynamiques.md:126
#: src/administration_manual/reference/parametres-dynamiques.md:127
msgid "`false`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:109
msgid "Autoriser l'inscription publique"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:110
#: src/administration_manual/reference/parametres-dynamiques.md:187
msgid "`validation_email_required`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:110
#: src/administration_manual/reference/parametres-dynamiques.md:118
#: src/administration_manual/reference/parametres-dynamiques.md:129
#: src/administration_manual/reference/parametres-dynamiques.md:130
msgid "`true`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:110
msgid "Exiger la validation email"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:111
msgid "`audit_log_level`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:111
msgid "`INFO`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:111
msgid "Niveau de log d'audit"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:112
msgid "`audit_log_actions`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:112
msgid "`[\"create\",\"update\",\"delete\",\"reset_password\"]`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:112
msgid "Actions auditées"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:113
msgid "`password_min_length`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:113
msgid "`8`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:113
msgid "Longueur minimum mot de passe"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:114
msgid "`password_require_uppercase`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:114
msgid "Exiger des majuscules"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:115
msgid "`password_require_lowercase`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:115
msgid "Exiger des minuscules"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:116
msgid "`password_require_digits`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:116
msgid "Exiger des chiffres"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:117
msgid "`password_require_special`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:117
msgid "Exiger des caractères spéciaux"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:118
msgid "`password_change_require_email`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:118
msgid "Confirmation email pour changement mdp"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:119
msgid "`password_expiration_enabled`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:119
msgid "Activer l'expiration des mots de passe"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:120
msgid "`password_expiration_days`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:120
msgid "`0`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:120
msgid "Durée d'expiration (jours)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:121
msgid "`password_expiration_alert_enabled`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:121
msgid "Alerte email avant expiration"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:122
msgid "`password_expiration_alert_days_before`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:122
msgid "`7`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:122
msgid "Jours avant expiration pour alerter"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:123
#: src/administration_manual/reference/parametres-dynamiques.md:188
msgid "`oauth_enabled`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:123
msgid "Activer OAuth/SSO"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:124
msgid "`oauth_google_enabled`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:124
msgid "Activer Google OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:125
msgid "`oauth_github_enabled`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:125
msgid "Activer GitHub OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:126
msgid "`oauth_discord_enabled`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:126
msgid "Activer Discord OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:127
msgid "`oauth_microsoft_enabled`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:127
msgid "Activer Microsoft OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:128
msgid "`oauth_redirect_base_url`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:128
#: src/administration_manual/reference/parametres-dynamiques.md:131
#: src/administration_manual/reference/parametres-dynamiques.md:132
#: src/administration_manual/reference/parametres-dynamiques.md:133
msgid "`\"\"`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:128
msgid "URL de base pour les callbacks OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:129
msgid "`oauth_auto_register`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:129
msgid "Créer un compte auto au premier login OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:130
msgid "`oauth_link_existing_account`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:130
msgid "Lier un compte OAuth à un utilisateur existant"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:131
msgid "`oauth_{provider}_client_id`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:131
msgid "Client ID du provider OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:132
msgid "`oauth_{provider}_client_secret`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:132
msgid "Client secret (chiffré AES-256-GCM en base)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:133
msgid "`oauth_microsoft_tenant`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:133
msgid "Tenant Azure AD"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:137
msgid "3. Cas hybride : OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:139
msgid ""
"OAuth est le **seul sous-système** qui combine les deux sources. La logique "
"dans `OAuthConfig::load()` :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:149
msgid ""
"**Important** : `OAuthConfig::load()` est appelé au démarrage. Le résultat "
"est stocké dans un `Arc` et n'est pas relu dynamiquement. Donc :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:151
msgid ""
"Modifier un réglage OAuth **via l'UI admin** nécessite un **redémarrage** "
"pour que `OAuthConfig` soit rechargé"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:152
msgid "Le `.env` n'est qu'un fallback si la DB n'a pas de valeur"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:156
msgid "4. Précédence et comportement au redémarrage"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:158
msgid "Réglages statiques (`.env` uniquement)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:160
#: src/administration_manual/reference/parametres-dynamiques.md:166
#: src/administration_manual/reference/parametres-dynamiques.md:173
#: src/developer_manual/how-to/lancer-tests-unitaires.md:170
#: src/developer_manual/reference/architecture-crates.md:155
msgid "Action"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:160
#: src/administration_manual/reference/parametres-dynamiques.md:166
#: src/administration_manual/reference/parametres-dynamiques.md:173
msgid "Effet immédiat"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:160
#: src/administration_manual/reference/parametres-dynamiques.md:166
#: src/administration_manual/reference/parametres-dynamiques.md:173
msgid "Après restart"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:162
#: src/administration_manual/reference/parametres-dynamiques.md:176
msgid "Modifier `.env`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:162
#: src/administration_manual/reference/parametres-dynamiques.md:168
msgid "Oui"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:164
msgid "Réglages dynamiques (DB uniquement)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:168
#: src/administration_manual/reference/parametres-dynamiques.md:175
msgid "Modifier via UI admin"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:168
msgid "Oui (valeur en DB persiste)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:169
msgid "Modifier le `.env`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:169
msgid "Aucun effet"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:171
msgid "Réglages hybrides (OAuth)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:175
msgid "Non (OAuthConfig est en Arc)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:175
msgid "Oui (DB prime sur .env)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:176
msgid "Seulement si aucune valeur en DB"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:180
msgid "5. Piège principal : les variables `.env` fantômes"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:182
msgid ""
"Certaines variables présentes dans `.env.example` donnent l'**illusion** de "
"configurer des réglages qui sont en réalité gérés par la base de données :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:184
msgid "Variable `.env`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:184
msgid "Réglage DB correspondant"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:184
msgid "La variable `.env` est-elle lue ?"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:186
msgid "`ALLOW_REGISTRATION=true`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:186
msgid "**Non** — valeur par défaut codée en dur (`\"false\"`)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:187
msgid "`EMAIL_VALIDATION_REQUIRED=true`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:187
msgid "**Non** — valeur par défaut codée en dur (`\"true\"`)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:188
msgid "`OAUTH_ENABLED=true`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:188
msgid "Oui, mais **seulement en fallback** si la DB n'a pas de valeur"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:190
msgid "Pour `ALLOW_REGISTRATION` et `EMAIL_VALIDATION_REQUIRED` :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:192
msgid ""
"La variable `.env` est documentée dans `.env.example` mais **n'est jamais "
"consultée** par `initialize_default_settings()`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:193
msgid "La valeur initiale est **codée en dur** dans le service"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:194
msgid ""
"Seule la valeur en base de données (modifiable via `/admin/settings`) fait "
"foi"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:196
msgid ""
"Pour `app_domain`, c'est le seul réglage dynamique qui lit le `.env` comme "
"seed initial."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:200
msgid "6. Diagramme de décision"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:224
msgid "7. Guide pour les administrateurs"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:226
msgid "Modifier un réglage d'infrastructure"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:228
msgid "Éditer `.env` (ou `.env.production`) puis redémarrer le service :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:231
msgid "# Éditer\n"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:233
msgid "# Redémarrer\n"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:235
msgid "# production\n"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:236
msgid "# dev\n"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:239
msgid "Modifier un réglage fonctionnel"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:241
msgid ""
"Se connecter en tant qu'administrateur, aller dans `/admin/settings`, "
"modifier la valeur, et cliquer \"Save\". L'effet est **immédiat**, aucun "
"redémarrage nécessaire."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:243
msgid "Modifier un réglage OAuth"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:245
msgid ""
"Via `/admin/settings`, modifier les valeurs OAuth puis **redémarrer le "
"service** (la config OAuth est chargée en mémoire au boot et n'est pas relue "
"dynamiquement)."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:247
msgid "Vérifier la valeur effective d'un réglage"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:249
msgid "Pour les réglages dynamiques, interroger la base directement :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:254
msgid "'allow_registration'"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:257
msgid ""
"Pour les réglages statiques, vérifier les logs au démarrage "
"(`RUST_LOG=debug`)."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:261
msgid "8. Guide pour les développeurs"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:263
msgid "Ajouter un nouveau réglage dynamique"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:265
msgid ""
"Ajouter le tuple `(clé, valeur_défaut, description)` dans "
"`AppSettingsService::initialize_default_settings()` :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:267
#: src/administration_manual/reference/parametres-dynamiques.md:273
#: src/administration_manual/reference/parametres-dynamiques.md:276
msgid "\"ma_nouvelle_cle\""
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:267
msgid "\"valeur_par_defaut\""
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:267
msgid "\"Description pour l'UI admin\""
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:270
msgid "Lire la valeur dans le code via le service :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:272
msgid "// Boolean avec défaut\n"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:275
msgid "// String\n"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:279
msgid "La valeur apparaîtra automatiquement dans `/admin/settings`."
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:281
msgid "Ajouter un nouveau réglage statique"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:283
msgid "Ajouter la variable dans `.env.example` avec documentation complète"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:284
msgid "Lire la variable dans le struct `Config` correspondant via `env::var()`"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:285
msgid "La valeur ne sera **pas** visible dans l'interface admin"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:287
msgid "Ajouter un réglage hybride (DB + fallback .env)"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:289
msgid ""
"Suivre le pattern OAuth dans `crates/rustwarden-core/src/config/oauth.rs` :"
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:292
msgid "\"ma_cle\""
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:294
msgid "\"MA_CLE\""
msgstr ""

#: src/administration_manual/reference/parametres-dynamiques.md:294
msgid "\"defaut\""
msgstr ""

#: src/developer_manual/index.md:3
msgid ""
"Ce manuel s'adresse à deux publics : les contributeurs au code gitrust (core "
"ou via fork rustwarden) et les développeurs externes qui construisent des "
"intégrations sur l'API publique. Il fournit tout le nécessaire pour "
"comprendre l'architecture des 6 crates, contribuer du code conforme aux "
"standards du projet, ou bâtir un client qui parle à l'API gitrust. Il ne "
"couvre pas l'installation d'une instance de production ni l'usage quotidien "
"de la forge."
msgstr ""

#: src/developer_manual/index.md:5
msgid "Parcours d'apprentissage — contributeur core"
msgstr ""

#: src/developer_manual/index.md:7
msgid ""
"Le parcours contributeur représente environ 4 heures au total, avec un "
"étayage dégressif : le premier tutoriel est entièrement guidé, le troisième "
"(capstone) demande de résoudre sans guide pas-à-pas."
msgstr ""

#: src/developer_manual/index.md:17
msgid ""
"**Checkpoint de parcours** : avant de passer au tutoriel 02, vous devez "
"avoir compilé gitrust localement, lancé les tests unitaires et obtenu une "
"instance de développement fonctionnelle. Si ce n'est pas le cas, relisez le "
"tutoriel 01."
msgstr ""

#: src/developer_manual/index.md:19
msgid ""
"**Checkpoint de parcours** : avant le tutoriel 03 (capstone), vous devez "
"avoir soumis une PR complète avec tests, passé la gate QA et reçu une "
"review. Si ce n'est pas le cas, relisez le tutoriel 02."
msgstr ""

#: src/developer_manual/index.md:27
msgid ""
"[01 — Getting started : build local, tests, instance de dev](tutorials/01-"
"getting-started.md) — ~45 min"
msgstr ""

#: src/developer_manual/index.md:28
msgid ""
"[02 — Première contribution : clone, build, test, PR](tutorials/02-premiere-"
"contribution.md) — ~90 min"
msgstr ""

#: src/developer_manual/index.md:29
msgid ""
"[03 — Créer un worker async (capstone)](tutorials/03-creer-un-worker-async."
"md) — ~120 min"
msgstr ""

#: src/developer_manual/index.md:37
msgid ""
"[Workflow de contribution : Git + review + QA](how-to/contribuer-workflow-pr."
"md)"
msgstr ""

#: src/developer_manual/index.md:38
msgid "[Lancer les tests unitaires](how-to/lancer-tests-unitaires.md)"
msgstr ""

#: src/developer_manual/index.md:39
msgid "[Lancer les tests E2E (Playwright)](how-to/lancer-tests-e2e.md)"
msgstr ""

#: src/developer_manual/index.md:40
msgid ""
"[Ajouter une route web (patron rustwarden → axum)](how-to/ajouter-route-web."
"md)"
msgstr ""

#: src/developer_manual/index.md:41
msgid "[Ajouter un service métier](how-to/ajouter-service-metier.md)"
msgstr ""

#: src/developer_manual/index.md:42
msgid ""
"[Ajouter une migration de base de données](how-to/ajouter-migration-db.md)"
msgstr ""

#: src/developer_manual/index.md:43
msgid "[Implémenter des webhooks](how-to/implementer-webhooks.md)"
msgstr ""

#: src/developer_manual/index.md:44
msgid "[Implémenter un endpoint API](how-to/implementer-endpoint-api.md)"
msgstr ""

#: src/developer_manual/index.md:45
msgid ""
"[Importer un dépôt externe (code)](how-to/importer-depot-externe-code.md)"
msgstr ""

#: src/developer_manual/index.md:46
msgid "[Contribuer à rustwarden upstream](how-to/contribuer-a-rustwarden.md)"
msgstr ""

#: src/developer_manual/index.md:47
msgid "[Passer la QA avant merge](how-to/passer-la-qa-avant-merge.md)"
msgstr ""

#: src/developer_manual/index.md:53
msgid ""
"La référence documente de façon exhaustive l'architecture, les API internes, "
"le schéma de données et les règles QA. Destinée à la consultation ponctuelle."
msgstr ""

#: src/developer_manual/index.md:55
msgid "[Architecture des 6 crates](reference/architecture-crates.md)"
msgstr ""

#: src/developer_manual/index.md:56
msgid "[Services et API interne](reference/services-api-interne.md)"
msgstr ""

#: src/developer_manual/index.md:57
msgid "[Schéma de base de données (ERD)](reference/schema-base-donnees.md)"
msgstr ""

#: src/developer_manual/index.md:58
msgid "[Règles QA et gates ANSSI](reference/regles-qa-anssi.md)"
msgstr ""

#: src/developer_manual/index.md:59
msgid ""
"[API REST v1 — auth, pagination, codes d'erreur](reference/api-rest-v1.md)"
msgstr ""

#: src/developer_manual/index.md:60
msgid "[Git hooks post-receive](reference/git-hooks-post-receive.md)"
msgstr ""

#: src/developer_manual/index.md:61
msgid ""
"[rustwarden-core API — helpers, extracteurs, middleware](reference/"
"rustwarden-core-api.md)"
msgstr ""

#: src/developer_manual/index.md:67
msgid ""
"Les explanations construisent les modèles mentaux nécessaires pour "
"contribuer de façon éclairée. Lisez-les quand vous voulez comprendre les "
"décisions d'architecture, pas seulement les appliquer."
msgstr ""

#: src/developer_manual/index.md:69
msgid ""
"[Vue d'ensemble de l'architecture gitrust](explanation/vue-ensemble-"
"architecture.md)"
msgstr ""

#: src/developer_manual/index.md:70
msgid ""
"[Flux de requêtes (diagrammes de séquence)](explanation/flux-requetes.md)"
msgstr ""

#: src/developer_manual/index.md:71
msgid ""
"[Modèle de permissions RBAC 4 niveaux](explanation/modele-permissions-rbac."
"md)"
msgstr ""

#: src/developer_manual/index.md:72
msgid "[Fonctionnement de la 2FA](explanation/2fa-fonctionnement.md)"
msgstr ""

#: src/developer_manual/index.md:73
msgid "[Hiérarchie des labels](explanation/hierarchie-labels.md)"
msgstr ""

#: src/developer_manual/index.md:74
msgid ""
"[CI Dagger : Easy Mode vs Power Mode](explanation/ci-dagger-easy-vs-power.md)"
msgstr ""

#: src/developer_manual/index.md:75
msgid "[Décisions UI : HTMX + DaisyUI](explanation/decisions-ui-htmx.md)"
msgstr ""

#: src/developer_manual/index.md:76
msgid "[Patron worker async](explanation/patron-worker-async.md)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:1
msgid ""
"Premiers pas avec gitrust : compilez, configurez et poussez votre premier "
"commit"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:3
msgid ""
"**Source** : ce tutoriel intègre le contenu de `gitrust/docs/GETTING_STARTED."
"md` avec la structure pédagogique complète (objectifs Bloom, modèle mental, "
"checkpoints observables, section « Et si ça ne marche pas »)."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:9
msgid ""
"**O1. Compiler** gitrust depuis les sources et lancer l'instance de "
"développement localement"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:10
msgid ""
"**O2. Configurer** l'environnement de développement (base de données, "
"variables d'environnement, assets CSS)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:11
msgid ""
"**O3. Exécuter** un premier push SSH vers votre instance locale et vérifier "
"le résultat dans l'interface web"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:15
msgid ""
"**Technique** : Rust stable ≥ 1.80 (`rustc --version`), PostgreSQL ≥ 15 "
"(`psql --version`), Node.js ≥ 18 (`node --version`), Git 2.x (`git --"
"version`), Docker (optionnel, recommandé pour la base de données)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:16
msgid ""
"**Pédagogique** : être un utilisateur autonome de gitrust (parcours "
"`user_manual` complété ou équivalent) ; familiarité avec Rust (au moins 3 "
"mois de pratique) et avec HTTP/PostgreSQL"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:17
msgid "**Temps estimé** : ~45 minutes"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:21
msgid ""
"Avant d'exécuter la première commande, prenons 3 minutes pour comprendre ce "
"que vous allez monter et comment les pièces s'articulent."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:23
msgid ""
"gitrust est un **monorepo Rust à 6 crates** qui compile en un seul binaire. "
"Quand vous lancez `cargo run`, ce binaire démarre deux serveurs "
"simultanément : un serveur HTTP (`:4000`) pour l'interface web et l'API "
"REST, et un serveur SSH (`:2222`) pour les opérations `git push/pull`. Ils "
"partagent la même base de données PostgreSQL et le même stockage de dépôts "
"bare sur disque."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:25
msgid ""
"```mermaid\n"
"graph TB\n"
"    subgraph sources [\"Sources gitrust (monorepo Rust)\"]\n"
"        C1[rustwarden-core<br/>auth, sessions, middleware]\n"
"        C2[gitrust-core<br/>modèles, services métier]\n"
"        C3[gitrust-git<br/>opérations Git bare]\n"
"        C4[gitrust-web<br/>handlers HTTP + templates]\n"
"        C5[gitrust-ssh<br/>serveur SSH Git]\n"
"        C6[gitrust-hooks<br/>post-receive, pre-receive]\n"
"    end\n"
"\n"
"    subgraph runtime [\"Processus unique (cargo run)\"]\n"
"        HTTP[\"HTTP :4000<br/>UI + API REST\"]\n"
"        SSH[\"SSH :2222<br/>git push/pull\"]\n"
"    end\n"
"\n"
"    subgraph storage [\"Stockage\"]\n"
"        PG[(PostgreSQL<br/>comptes, dépôts,<br/>issues, PRs)]\n"
"        REPOS[Dépôts bare<br/>data/repos/]\n"
"    end\n"
"\n"
"    C1 & C2 & C3 & C4 & C5 & C6 -->|cargo build| HTTP\n"
"    C1 & C2 & C3 & C4 & C5 & C6 -->|cargo build| SSH\n"
"    HTTP & SSH --> PG\n"
"    HTTP & SSH --> REPOS\n"
"```"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:52
msgid ""
"**Ce que vous allez faire** : cloner les sources → préparer PostgreSQL → "
"copier et remplir `.env` → compiler les assets CSS → lancer `cargo run` → "
"vérifier l'instance → pousser un premier commit via SSH."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:56
msgid "Étape 1 : Vérifiez les pré-requis système"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:58
msgid ""
"Avant de cloner quoi que ce soit, vérifiez que tous les outils nécessaires "
"sont installés :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:64
msgid "Sortie attendue (versions exactes peuvent varier) :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:73
msgid "Si des dépendances système manquent, installez-les :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:76
msgid "# Debian / Ubuntu\n"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:78
msgid "# macOS\n"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:83
msgid ""
"**Checkpoint** : toutes les commandes de vérification doivent retourner un "
"numéro de version sans erreur. Si `rustc` n'est pas trouvé, installez Rust "
"via `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` puis "
"rechargez votre shell."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:87
msgid "Étape 2 : Clonez le projet"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:102
msgid "**Checkpoint** : vérifiez que la structure de crates est présente :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:115
msgid "Étape 3 : Configurez l'environnement (.env)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:117
msgid "Copiez le fichier d'exemple et éditez les 5 valeurs essentielles :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:123
msgid "Ouvrez `.env` dans votre éditeur et renseignez ces valeurs :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:125
msgid ""
"```env\n"
"# Connexion à la base de données\n"
"DATABASE_URL=postgres://gitrust:motdepasse@localhost:5432/gitrust\n"
"\n"
"# Clé secrète JWT (générez-la avec : openssl rand -hex 32)\n"
"JWT_SECRET=votre_cle_secrete_64_caracteres\n"
"\n"
"# Compte administrateur créé au premier lancement\n"
"ADMIN_USERNAME=admin\n"
"ADMIN_EMAIL=admin@example.com\n"
"ADMIN_PASSWORD=MotDePasseFort123!\n"
"```"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:138
msgid ""
"Les autres variables ont des valeurs par défaut raisonnables pour le "
"développement. Consultez `.env.example` pour la liste complète."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:140
msgid "Générez une vraie valeur pour `JWT_SECRET` :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:146
msgid "Sortie attendue (valeur différente à chaque exécution) :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:151
msgid "Copiez cette valeur dans `.env` pour `JWT_SECRET`."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:153
msgid ""
"**Checkpoint** : vérifiez qu'aucune valeur d'exemple reste dans `.env` :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:156
msgid "\"votre_cle|example\\.com|MotDePasse\""
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:159
msgid ""
"La commande doit retourner vide (aucune ligne). Si elle retourne des lignes, "
"ces valeurs placeholder sont encore présentes — l'application démarrera mais "
"avec une configuration non sécurisée."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:163
msgid "Étape 4 : Préparez la base de données PostgreSQL"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:165
msgid "Vous avez deux options :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:167
msgid "**Option A — Docker (recommandé pour débuter) :**"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:180
msgid "**Option B — PostgreSQL existant sur la machine :**"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:183
msgid ""
"<< 'SQL'\n"
"CREATE USER gitrust WITH PASSWORD 'motdepasse';\n"
"CREATE DATABASE gitrust OWNER gitrust;\n"
"SQL\n"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:195
msgid ""
"Adaptez le mot de passe dans `DATABASE_URL` dans `.env` si vous utilisez "
"l'option B."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:197
msgid ""
"**Checkpoint** : vérifiez que la base est accessible depuis l'application :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:200
msgid "\"$DATABASE_URL\""
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:200
msgid "\"SELECT version();\""
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:211
msgid ""
"Si vous obtenez `psql: error: connection to server failed`, vérifiez que "
"PostgreSQL tourne et que `DATABASE_URL` correspond."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:215
msgid "Étape 5 : Compilez les assets CSS"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:217
msgid ""
"gitrust utilise Tailwind CSS + DaisyUI. Les assets doivent être compilés "
"localement — aucun CDN, tous les fichiers sont servis depuis `static/` :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:232
msgid "**Checkpoint** : vérifiez que le fichier CSS est généré :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:243
msgid ""
"Si le fichier fait 0 octet ou n'existe pas, la compilation a échoué — "
"relancez `npm install` puis la commande `npx tailwindcss`."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:247
msgid "Étape 6 : Lancez l'application"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:253
msgid ""
"La première compilation prend 2 à 5 minutes (toutes les dépendances sont "
"compilées). Les compilations suivantes sont incrémentales et beaucoup plus "
"rapides."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:255
msgid "Au premier lancement, gitrust exécute automatiquement :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:256
msgid "Les migrations de base de données (création de toutes les tables)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:257
msgid "La création du compte administrateur (depuis `.env`)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:258
msgid "La génération de la clé SSH host (`data/ssh_host_ed25519_key`)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:259
msgid "La création du répertoire de stockage des dépôts (`data/repos/`)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:261
msgid "Sortie attendue (après compilation) :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:262
msgid ""
"```\n"
"   Compiling gitrust-web v0.9.0 (/home/vous/gitrust/crates/gitrust-web)\n"
"    Finished `dev` profile [unoptimized + debuginfo] target(s) in 187.42s\n"
"     Running `target/debug/gitrust`\n"
"2026-04-17T10:20:00Z INFO  gitrust > Starting gitrust v0.9.0\n"
"2026-04-17T10:20:00Z INFO  gitrust > Running database migrations... applied "
"42\n"
"2026-04-17T10:20:01Z INFO  gitrust > Admin account created: admin\n"
"2026-04-17T10:20:01Z INFO  gitrust > SSH host key: SHA256:"
"xxxxxxxxxxxxxxxxxxxx\n"
"Server listening on http://0.0.0.0:4000\n"
"```"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:273
msgid ""
"**Checkpoint** : ouvrez `http://localhost:4000` dans votre navigateur. Vous "
"devez voir la page d'accueil gitrust. Connectez-vous avec les identifiants "
"`ADMIN_USERNAME` / `ADMIN_PASSWORD` définis dans `.env`. Si la page ne "
"charge pas, vérifiez que le message `Server listening on "
"http://0.0.0.0:4000` est bien apparu dans les logs."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:277
msgid "Étape 7 : Créez un dépôt et poussez votre premier commit"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:279
msgid ""
"Dans l'interface web (`http://localhost:4000`), cliquez sur **« New "
"repository »**, donnez un nom (ex. `mon-projet`) et cliquez **Créer**."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:281
msgid ""
"Ajoutez votre clé SSH publique dans **Settings > SSH Keys** en collant le "
"contenu de `~/.ssh/id_ed25519.pub`."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:283
msgid "Puis dans votre terminal :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:289
msgid "\"# Mon projet\""
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:291
msgid "\"Initial commit\""
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:296
msgid ""
"```\n"
"Cloning into 'mon-projet'...\n"
"warning: You appear to have cloned an empty repository.\n"
"[main (root-commit) a1b2c3d] Initial commit\n"
" 1 file changed, 1 insertion(+)\n"
" create mode 100644 README.md\n"
"Enumerating objects: 3, done.\n"
"Counting objects: 100% (3/3), done.\n"
"Writing objects: 100% (3/3), 226 bytes | 226.00 KiB/s, done.\n"
"Total 3 (delta 0), reused 0 (delta 0), pack-reused 0\n"
"To ssh://localhost:2222/admin/mon-projet.git\n"
" * [new branch]      main -> main\n"
"```"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:310
msgid ""
"**Checkpoint** : retournez dans le navigateur sur `http://localhost:4000/"
"admin/mon-projet`. La page doit afficher le fichier `README.md` avec le "
"contenu `# Mon projet` et indiquer 1 commit sur la branche `main`."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:314
msgid "Fonctionnalités supplémentaires disponibles"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:316
msgid "CI intégrée (optionnelle)"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:318
msgid ""
"La CI s'exécute sur un serveur de build via SSH + rsync. Configurez dans `."
"env` :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:329
msgid "**Easy Mode** — ajoutez `.gitrust-ci.yml` à la racine de votre dépôt :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:332
msgid "language"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:338
msgid "\"cargo test\""
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:341
msgid ""
"**Power Mode** — placez un module Dagger dans `.dagger/` à la racine. "
"gitrust exécutera `dagger call -m .dagger/ ci`."
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:345
msgid "Configurez SMTP dans `.env` pour les notifications e-mail :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:355
msgid "Langue de l'interface"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:357
msgid ""
"gitrust est disponible en 6 langues (fr, en, de, es, pt, it). Définissez la "
"langue par défaut de l'instance :"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:367
msgid ""
"✓ **O1 accompli** : gitrust est compilé depuis les sources et tourne "
"localement — `cargo run` affiche « Server listening on http://0.0.0.0:4000 »"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:368
msgid ""
"✓ **O2 accompli** : l'environnement est configuré — `.env` rempli, "
"PostgreSQL connecté, assets CSS générés, migrations appliquées"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:369
msgid ""
"✓ **O3 accompli** : un premier push SSH a réussi — le commit est visible "
"dans l'interface web à `http://localhost:4000/admin/mon-projet`"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:377
msgid "`error[E0463]: can't find crate for 'std'` à la compilation"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:377
msgid "Toolchain Rust manquante ou mauvaise version"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:377
msgid ""
"Exécutez `rustup update stable && rustup default stable`. Vérifiez avec "
"`rustc --version` ≥ 1.80"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:378
msgid ""
"`connection to server on socket \"/var/run/postgresql/.s.PGSQL.5432\" failed`"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:378
msgid "PostgreSQL non démarré ou `DATABASE_URL` incorrect"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:378
msgid ""
"Démarrez PostgreSQL (`sudo systemctl start postgresql` ou `docker compose up "
"-d` dans `database/`). Vérifiez que `DATABASE_URL` dans `.env` correspond"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:379
msgid "`Permission denied (publickey)` lors du `git push`"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:379
msgid "Clé SSH non enregistrée dans gitrust ou mauvais port"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:379
msgid ""
"Vérifiez dans _Settings > SSH Keys_ que la clé est présente. Testez avec "
"`ssh -T git@localhost -p 2222` — vous devez voir « Vous êtes authentifié »"
msgstr ""

#: src/developer_manual/tutorials/01-getting-started.md:385
msgid ""
"→ [02 — Première contribution : clone, build, test, PR](02-premiere-"
"contribution.md) : apprenez à créer une feature branch, écrire des tests, et "
"soumettre votre première pull request en suivant le workflow gitrust (~90 "
"min)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:3
msgid "Référence des commandes et de la stratégie de tests pour gitrust."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:5
msgid "Infrastructure existante"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:7
msgid "Tests unitaires Rust"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:10
msgid "# Tous les tests\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:11
msgid "# Un crate spécifique\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:12
msgid "# Tests Git (tempdir)\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:15
msgid "Les tests unitaires sont intégrés dans chaque crate via `#[cfg(test)]`."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:17
msgid "Tests e2e Playwright"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:19
msgid ""
"17 specs couvrant : auth, admin, repos, issues, labels, teams, tokens, "
"settings, navigation."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:22
msgid "# Pré-requis (première fois)\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:24
msgid "# Crée la DB gitrust_test\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:25
msgid "# Lancer les tests\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:27
msgid "# Mode headless\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:28
msgid "# Mode interactif (navigateur visible)\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:29
msgid "# Mode debug\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:30
msgid "# Voir le rapport HTML\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:33
msgid ""
"Configuration : `playwright.config.ts` (port 4001, DB `gitrust_test`, locale "
"`fr-FR`)."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:35
msgid "Structure des répertoires"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:56
msgid "Tests à ajouter"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:58
msgid "1. Tests fonctionnels API REST (intégration Rust)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:60
msgid "Tests avec une DB PostgreSQL réelle pour vérifier les endpoints API."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:62
msgid "**Emplacement** : `tests/integration/` ou `crates/gitrust-web/tests/`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:64
msgid "**Approche recommandée** : utiliser `reqwest` + un serveur de test :"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:67
msgid "// tests/integration/api_test.rs\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:71
msgid "// Nécessite une DB + serveur running\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:74
msgid "\"http://localhost:4001/api/v1/auth/login\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:76
msgid "\"login\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:76
msgid "\"admin\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:77
msgid "\"password\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:77
msgid "\"test_password\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:86
msgid ""
"**Alternative** : `axum::test` pour tester les handlers sans serveur HTTP :"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:95
msgid "// Build router with test DB\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:97
msgid "\"/api/hello\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:104
msgid "2. Tests fonctionnels CI"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:106
#: src/developer_manual/how-to/lancer-tests-e2e.md:89
#: src/developer_manual/how-to/lancer-tests-e2e.md:103
#: src/developer_manual/how-to/lancer-tests-e2e.md:114
#: src/developer_manual/how-to/lancer-tests-e2e.md:125
msgid "Test"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:106
msgid "Priorité"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:108
msgid "CI detection"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:108
msgid "Repo avec `.gitrust-ci.yml` -> Easy, `.dagger/` -> Power, rien -> None"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:108
#: src/developer_manual/how-to/lancer-tests-unitaires.md:109
#: src/developer_manual/how-to/lancer-tests-unitaires.md:110
msgid "Haute"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:109
msgid "Pipeline CRUD"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:109
msgid "Créer, lister, mettre à jour, annuler un pipeline"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:110
msgid "Config CI"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:110
msgid "Activer/désactiver CI, modifier triggers, vérifier effet"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:111
msgid "Variables héritage"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:111
msgid "Team var + repo var -> merge correct"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:111
#: src/developer_manual/how-to/lancer-tests-unitaires.md:112
#: src/developer_manual/how-to/lancer-tests-unitaires.md:113
#: src/developer_manual/how-to/lancer-tests-unitaires.md:114
msgid "Moyenne"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:112
msgid "Auto-cancel"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:112
msgid "Nouveau push annule les pipelines en cours"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:113
msgid "Logs streaming"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:113
msgid "Append logs + lecture paginée"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:114
msgid "Notifications CI"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:114
msgid "Pipeline échoue -> notification créée"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:116
msgid ""
"**Pour les tests CI** : mocker `dagger` avec un script shell qui simule "
"success/failure :"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:119
msgid "#!/bin/bash\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:121
msgid "\"Step 1: Building...\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:122
msgid "\"Step 2: Testing...\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:123
msgid "\"$MOCK_FAIL\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:123
msgid "\"true\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:124
msgid "\"FAILED\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:127
msgid "\"All checks passed\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:131
msgid ""
"Configurer `CI_DAGGER_BIN=tests/fixtures/mock-dagger.sh` dans les tests."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:133
msgid "3. Tests e2e Playwright à ajouter"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:135
msgid "Nouvelles specs pour les fonctionnalités CI et notifications :"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:137
msgid "Spec"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:137
msgid "Couverture"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:139
msgid "`ci-pipelines.spec.ts`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:139
msgid "Liste pipelines, détail, status badges"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:140
msgid "`ci-config.spec.ts`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:140
msgid "Config CI (enable/disable, triggers, timeout)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:141
msgid "`ci-variables.spec.ts`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:141
msgid "CRUD variables CI, masquage secrets"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:142
msgid "`notifications.spec.ts`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:142
msgid "Liste notifications, marquer lu, préférences"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:143
msgid "`api-docs.spec.ts`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:143
msgid "Swagger UI accessible, spec chargée"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:144
msgid "`i18n.spec.ts`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:144
msgid "Changement de langue, textes traduits"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:145
msgid "`docker-smoke.spec.ts`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:145
msgid "`docker compose up` + smoke test"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:147
msgid "**Exemple de spec CI** :"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:149
msgid ""
"```typescript\n"
"// tests/e2e/ci-pipelines.spec.ts\n"
"import { test, expect } from './fixtures';\n"
"\n"
"test.describe('CI Pipelines', () => {\n"
"  test('affiche la page CI vide', async ({ authenticatedPage }) => {\n"
"    await authenticatedPage.goto('/admin/mon-repo/ci');\n"
"    await expect(authenticatedPage.locator('text=Aucun pipeline'))."
"toBeVisible();\n"
"  });\n"
"\n"
"  test('bouton trigger CI visible pour le maintainer', async "
"({ authenticatedPage }) => {\n"
"    await authenticatedPage.goto('/admin/mon-repo/ci');\n"
"    await expect(authenticatedPage.locator('text=Lancer CI'))."
"toBeVisible();\n"
"  });\n"
"});\n"
"```"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:166
msgid "4. Tests settings ↔ comportement"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:168
msgid ""
"Les tests les plus critiques vérifient que **changer un setting modifie le "
"comportement observable** :"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:170
msgid "Setting"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:170
msgid "Vérification"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:172
msgid "PAT révoqué"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:172
msgid "Appel API"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:172
msgid "401 immédiatement"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:173
msgid "`ci_enabled = false`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:173
#: src/developer_manual/how-to/lancer-tests-unitaires.md:174
msgid "Push"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:173
msgid "Pas de pipeline créé"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:174
msgid "`trigger_on_push = false`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:174
msgid "Pas de pipeline"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:175
msgid "`auto_cancel = true`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:175
msgid "2 pushes rapides"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:175
msgid "1er pipeline annulé"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:176
msgid "`email_on_pipeline_failure = false`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:176
msgid "Pipeline échoue"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:176
msgid "Pas d'email, notif in-app ok"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:177
msgid "`DEFAULT_LOCALE = en`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:177
msgid "Charger page"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:177
msgid "Texte en anglais"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:181
msgid "Commandes de test"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:184
msgid "# Tests unitaires Rust\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:186
msgid "# Tests avec filtrage\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:190
msgid "# Tests e2e Playwright\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:193
msgid "# Tests e2e spécifiques\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:196
msgid "\"notifications\""
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:197
msgid "# Lint\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:200
msgid "# Format check\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:207
msgid "CI locale (exécuter avant un push)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-unitaires.md:210
msgid "# Script rapide de vérification pré-push\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:1
msgid "Lancer les tests end-to-end (E2E)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:3
msgid ""
"Les tests E2E de gitrust utilisent **Playwright** pour piloter un navigateur "
"Chromium contre une instance de l'application configurée avec une base de "
"données et un répertoire de dépôts dédiés."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:7
msgid "Node.js (déjà présent pour Tailwind/DaisyUI)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:8
msgid ""
"PostgreSQL accessible en local (Docker via `database/docker-compose.yml`)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:9
msgid "`psql`, `createdb`, `dropdb` disponibles dans le PATH"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:10
msgid "Chromium installé via Playwright (`npx playwright install chromium`)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:12
msgid "Commandes"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:15
msgid "# Créer (ou remettre à zéro) la base de données de test\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:17
msgid "# Lancer tous les tests E2E\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:20
msgid "# Mode debug interactif (inspecteur Playwright, pas-à-pas)\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:23
msgid "# Mode UI (interface graphique Playwright)\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:26
msgid "# Consulter le rapport HTML après exécution\n"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:31
msgid "Architecture"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:51
msgid "Isolation de l'environnement de test"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:53
msgid "Ressource"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:53
msgid "Développement"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:53
msgid "Tests E2E"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:55
msgid "Base de données"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:55
msgid "`gitrust`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:55
msgid "`gitrust_test`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:56
msgid "Port HTTP"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:56
msgid "`4000`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:56
msgid "`4001`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:57
msgid "Port SSH"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:57
msgid "`2222`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:57
msgid "`2223`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:58
msgid "Dépôts Git"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:58
msgid "`./data/repos/`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:58
msgid "`./depot_test/`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:59
msgid "Rate limiting"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:59
msgid "Standard"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:59
msgid "Relâché (×20)"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:60
msgid "Validation email"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:60
msgid "Activée"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:60
msgid "Désactivée"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:62
msgid "Fonctionnement"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:64
msgid ""
"**`npm run test:e2e:setup`** supprime puis recrée la base `gitrust_test` et "
"vide `depot_test/`."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:65
msgid ""
"**Playwright** démarre automatiquement l'application via `scripts/e2e-server."
"sh`, qui charge les variables de `.env.test` avant d'exécuter `cargo run`."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:66
msgid ""
"Le **global-setup** crée les utilisateurs de test (alice, bob, charlie) en "
"passant par le formulaire `/register` — approche 100% E2E, aucune insertion "
"directe en base."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:67
msgid ""
"Les **tests** s'exécutent séquentiellement (un seul worker) pour éviter les "
"conflits sur la DB partagée."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:68
msgid "Le **global-teardown** est exécuté à la fin de la session."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:70
msgid "Fixtures"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:72
msgid ""
"Le fichier `fixtures.ts` fournit une fixture `loginAs` réutilisable dans "
"tous les tests :"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:74
msgid ""
"```typescript\n"
"import { test, expect } from './fixtures';\n"
"\n"
"test('mon test', async ({ page, loginAs }) => {\n"
"  await loginAs('alice');\n"
"  // alice est connectée, on peut naviguer\n"
"});\n"
"```"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:83
msgid "Utilisateurs disponibles : `admin`, `alice`, `bob`, `charlie`."
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:85
msgid "Liste des tests"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:87
msgid "`auth.spec.ts` — Authentification"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:91
msgid "login avec des identifiants valides"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:91
msgid "Vérifie le login standard et la redirection vers `/dashboard`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:92
msgid "login avec un mauvais mot de passe"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:92
msgid "Vérifie l'affichage d'un message d'erreur"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:93
msgid "login avec un utilisateur inexistant"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:93
msgid "Vérifie le rejet d'un username inconnu"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:94
msgid "logout déconnecte l'utilisateur"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:94
msgid "Vérifie la déconnexion et l'impossibilité d'accéder au dashboard"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:95
msgid "accès au dashboard sans login redirige vers login"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:95
msgid "Vérifie la protection des routes authentifiées"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:96
msgid "option remember me est présente"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:96
msgid "Vérifie la présence de la checkbox remember_me"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:97
msgid "formulaire d'inscription est accessible"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:97
msgid "Vérifie la présence de tous les champs du formulaire"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:98
msgid "inscription avec username déjà pris échoue"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:98
msgid "Vérifie l'unicité des usernames"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:99
msgid "inscription avec mots de passe différents échoue"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:99
msgid "Vérifie la validation de confirmation du mot de passe"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:101
msgid "`repository.spec.ts` — Gestion des dépôts"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:105
msgid "créer un dépôt avec nom et description"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:105
msgid "Crée un dépôt complet et vérifie la redirection"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:106
msgid "créer un dépôt sans description"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:106
msgid "Vérifie que la description est optionnelle"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:107
msgid "créer un dépôt avec un nom déjà pris échoue"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:107
msgid "Vérifie l'unicité des slugs par utilisateur"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:108
msgid "le formulaire de création nécessite un login"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:108
msgid "Vérifie la protection de la route `/new`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:109
msgid "le dashboard liste les dépôts de l'utilisateur"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:109
msgid "Vérifie l'affichage des dépôts sur le dashboard"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:110
msgid "un dépôt public est accessible sans login"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:110
msgid "Vérifie l'accès anonyme aux dépôts publics"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:112
msgid "`admin.spec.ts` — Administration"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:116
msgid "l'admin peut accéder au panneau d'administration"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:116
msgid "Vérifie l'accès admin à `/admin`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:117
msgid "un utilisateur normal ne peut pas accéder à l'admin"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:117
msgid "Vérifie le contrôle d'accès"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:118
msgid "lister les utilisateurs"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:118
msgid "Vérifie l'affichage de la liste des utilisateurs"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:119
msgid "créer un nouvel utilisateur via l'admin"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:119
msgid "Teste le formulaire de création d'utilisateur admin"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:120
msgid "créer un utilisateur avec un username déjà pris échoue"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:120
msgid "Vérifie la gestion des doublons côté admin"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:121
msgid "les liens du menu admin sont présents"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:121
msgid "Vérifie la navigation du panneau admin"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:123
msgid "`navigation.spec.ts` — Navigation et UI"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:127
msgid "la page de login est accessible"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:127
msgid "Vérifie le rendu de la page de login"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:128
msgid "la navbar est présente après login"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:128
msgid "Vérifie la présence de la barre de navigation"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:129
msgid "le sidebar est présent après login"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:129
msgid "Vérifie la présence du menu latéral"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:130
msgid "le lien vers le dashboard fonctionne"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:130
msgid "Vérifie la navigation vers le dashboard"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:131
msgid "le lien vers la création de dépôt fonctionne"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:131
msgid "Vérifie le lien `/new`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:132
msgid "la page utilise le thème DaisyUI"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:132
msgid "Vérifie la présence de l'attribut `data-theme`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:134
msgid "Ajouter un nouveau test"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:136
msgid "Créer un fichier `tests/e2e/mon-module.spec.ts`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:137
msgid "Importer les fixtures : `import { test, expect } from './fixtures';`"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:138
msgid "Utiliser `loginAs` pour les tests nécessitant une authentification"
msgstr ""

#: src/developer_manual/how-to/lancer-tests-e2e.md:139
msgid ""
"Lancer avec `npm run test:e2e` ou cibler le fichier : `npx playwright test "
"mon-module`"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:3
msgid ""
"Référence du flux d'import de dépôts externes dans gitrust : rôle de la base "
"de données, schéma de séquence complet et pistes d'optimisation."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:5
msgid "1. Rôle de la base de données"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:7
msgid "Pendant un import, la DB sert **quatre fonctions distinctes** :"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:9
msgid "Table"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:9
msgid "Fréquence"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:11
msgid "**File d'attente persistante**"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:11
#: src/developer_manual/how-to/importer-depot-externe-code.md:12
msgid "`import_jobs`"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:11
msgid "1 INSERT à la création"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:12
msgid "**Suivi d'état pour l'UI**"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:12
msgid "1 UPDATE toutes les ~1.5 s"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:13
msgid "**Enregistrement final du dépôt**"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:13
msgid "`repositories` + `resources`"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:13
msgid "2 INSERT à la fin"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:14
msgid "**Journal d'audit**"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:14
msgid "`audit_log`"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:14
msgid "1 INSERT à la fin"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:16
msgid ""
"Le clone lui-même ne passe **jamais** par la DB : seuls les métadonnées et "
"compteurs de progression y transitent. Les objets Git sont écrits "
"directement sur disque dans `{GIT_REPOS_BASE_PATH}/{owner}/{slug}.git/`."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:18
msgid "Pourquoi persister l'état ?"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:20
msgid ""
"**Reprise après redémarrage** : le serveur peut crasher pendant un clone de "
"plusieurs minutes. La table permet de marquer ces jobs comme `failed` au "
"redémarrage."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:21
msgid ""
"**SSE** : l'UI lit la progression via un endpoint SSE qui interroge la DB "
"toutes les 2 s. Sans DB, il faudrait un canal in-memory plus un mécanisme de "
"routage vers le bon client."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:22
msgid ""
"**Multi-navigateurs** : si l'utilisateur ferme l'onglet puis le rouvre, il "
"retrouve l'état exact du job."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:23
msgid ""
"**Audit / historique** : conservation des imports passés avec leurs "
"statistiques."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:25
msgid "2. Schéma du flux actuel"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:91
msgid "3. Coût DB par import"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:93
msgid "Pour un clone de **90 secondes** avec throttle 1500 ms :"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:95
msgid "Étape"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:95
msgid "Opérations DB"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:95
msgid "Cumul"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:97
msgid "create_job"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:97
#: src/developer_manual/how-to/importer-depot-externe-code.md:105
msgid "1 INSERT"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:98
msgid "mark_running"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:98
#: src/developer_manual/how-to/importer-depot-externe-code.md:101
#: src/developer_manual/how-to/importer-depot-externe-code.md:104
msgid "1 SELECT + 1 UPDATE"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:99
msgid "update_progress pendant clone"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:99
msgid "~60 x (1 SELECT + 1 UPDATE)"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:99
msgid "123"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:100
msgid "check cancel"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:100
msgid "1 SELECT"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:100
msgid "124"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:101
msgid "update_progress finalizing"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:101
msgid "126"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:102
msgid "RepositoryService::create"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:102
msgid "2 INSERT (repo + resource)"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:102
msgid "128"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:103
msgid "update repositories"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:103
msgid "1 UPDATE"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:103
msgid "129"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:104
msgid "mark_success"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:104
msgid "131"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:105
msgid "audit log"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:105
msgid "132"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:106
msgid "SSE stream (45 ticks à 2 s)"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:106
msgid "45 SELECT"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:106
msgid "177"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:108
msgid ""
"**~177 requêtes pour un import**, dont **120+ sont des progress updates**."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:110
msgid "4. Pistes d'optimisation (sans changer libgit2)"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:112
msgid "4.1 Éliminer le SELECT avant UPDATE dans `update_progress`"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:114
msgid ""
"`update_progress` fait actuellement `load_model` (SELECT) puis `active."
"update(db)` (UPDATE + RETURNING). Le SELECT est redondant : on connaît l'ID, "
"on veut juste patcher 4 colonnes."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:116
msgid ""
"**Gain** : divise par 2 les requêtes de progression (~60 requêtes en moins "
"pour un clone de 90 s)."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:118
msgid ""
"Refonte suggérée avec `UpdateMany` (pattern déjà utilisé dans `ci_service."
"rs::cancel_running_pipelines`) :"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:132
msgid ""
"Même principe pour `mark_running`, `mark_success`, `mark_failed`, "
"`mark_cancelled` → toutes divisent leurs aller-retours DB par 2."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:134
msgid "4.2 Downsampler la progression dans le worker (dédié)"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:136
msgid ""
"Plan alternatif : le callback écrit simplement dans un `tokio::sync::"
"watch<TransferStats>` (en mémoire, zéro DB). Une **tâche dédiée** consomme "
"ce channel et UPDATE la DB à 1 Hz seulement."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:145
msgid "**Gains** :"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:146
msgid ""
"**1 seul émetteur DB** au lieu de N tokio::spawn concurrents → zéro "
"contention sur le pool"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:147
msgid "**Fréquence déterministe** (1 Hz) indépendante de la vitesse réseau"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:148
msgid "Code plus clair (la tâche est async, on peut `await` sans détour)"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:150
msgid "4.3 Supprimer le `RETURNING` implicite de SeaORM"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:152
msgid ""
"`ActiveModel::update(db)` renvoie le modèle complet via `... RETURNING *`. "
"Pour les progress updates, on n'utilise pas le retour. `UpdateMany::exec` "
"n'émet pas de `RETURNING` → moins de bytes sur le wire, moins de "
"désérialisation."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:154
msgid "4.4 Pool DB dédié pour le worker"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:156
msgid ""
"Aujourd'hui le worker partage le pool principal avec les handlers HTTP. Un "
"pool de 4-8 connexions dédié au worker éviterait qu'un import sature le pool "
"et fasse timeouter les requêtes utilisateur."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:158
msgid "4.5 Debouncer le SSE côté serveur"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:160
msgid ""
"Le SSE SELECT toutes les 2 s même quand rien ne change. Alternative : "
"**PostgreSQL LISTEN/NOTIFY** sur une chaîne `import_job_{uuid}`. Chaque "
"UPDATE émet un NOTIFY, la connexion SSE fait LISTEN → push direct, zéro "
"polling."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:162
msgid ""
"**Coût** : nécessite une connexion DB dédiée par SSE (LISTEN est stateful). "
"Compromis à évaluer."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:164
msgid "5. Optimisation majeure : shell-out vers `git clone --bare`"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:166
msgid ""
"**Indépendant des optimisations DB** mais de loin le plus gros gain. libgit2 "
"est structurellement 2-5x plus lent que `git` CLI sur gros clones HTTPS (pas "
"de multiplexage, résolution de deltas mono-threadée, etc.)."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:182
msgid "Avantages :"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:183
msgid "**Vitesse native** (parité avec `git` CLI)"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:184
msgid ""
"**Progression native** via stderr `Receiving objects: 42% (368/876), 1.10 "
"MiB | 2.05 MiB/s`"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:185
msgid ""
"**HEAD correctement positionné** (plus besoin du workaround `RepoBuilder`)"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:186
msgid "**Moins de dépendance sur libgit2** pour le cas du clone initial"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:188
msgid ""
"Contrepartie : binaire `git` requis sur le serveur (déjà le cas — utilisé "
"par `SbomService::git_archive`)."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:190
msgid "6. Priorités recommandées"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:192
msgid "Si on voulait optimiser maintenant, ordre proposé :"
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:194
msgid ""
"**Shell-out `git clone --bare`** — gain réel pour l'utilisateur (clone 3-5x "
"plus rapide)."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:195
msgid ""
"**`update_many` pour `update_progress`** — divise la pression DB par 2, "
"changement mécanique de ~20 lignes."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:196
msgid ""
"**`watch` channel + tâche 1 Hz** — architecture plus propre, élimine les "
"problèmes de pool."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:197
msgid "**Pool DB dédié worker** — filet de sécurité opérationnel."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:198
msgid "LISTEN/NOTIFY pour SSE — seulement si beaucoup de clients simultanés."
msgstr ""

#: src/developer_manual/how-to/importer-depot-externe-code.md:200
msgid ""
"Les gains 2-4 sont utiles même avec libgit2 ; le gain 1 est le plus visible "
"pour l'utilisateur final."
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:1
msgid "Contribuer à rustwarden"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:3
msgid ""
"Ce document décrit les interactions entre gitrust et le framework rustwarden-"
"core, et explique comment étendre le framework côté gitrust sans modifier "
"ses sources."
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:5
msgid "Services framework utilisés"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:7
msgid "Usage dans gitrust"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:9
msgid "`UserService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:9
msgid ""
"CRUD users, roles, `delete_user`, `admin_reset_password`, "
"`change_password_direct`, `unassign_role_from_user`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:10
msgid "`RoleService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:10
msgid "Liste/création/suppression roles, `get_role_by_name`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:11
msgid "`PasswordService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:11
msgid ""
"`hash_password` (async), `verify_password` (async), "
"`generate_secure_password`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:12
msgid "`ResourceService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:12
msgid ""
"`register`/`unregister` repos, `set_public`, `effective_permission`, "
"`find_by_type_and_id`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:13
msgid "`AuthService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:13
msgid "`authenticate_user` (login)"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:14
msgid "`JwtService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:14
msgid "`generate_token` (login)"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:15
msgid "`EmailValidationService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:15
msgid "Vérification email"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:16
msgid "`PasswordResetService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:16
msgid "Flux \"mot de passe oublié\""
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:17
msgid "`AppSettingsService`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:17
msgid "`get_bool` pour `registration_enabled`"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:19
msgid "Hook `on_user_deleted` implémenté"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:21
msgid ""
"Le hook `on_user_deleted` dans `gitrust-hooks` supprime le répertoire "
"utilisateur sur le filesystem (`repos_base_path/username/`) avant la cascade "
"DB. Appelé automatiquement par `UserService::delete_user`."
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:23
msgid "Règle fondamentale"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:25
msgid ""
"**Ne jamais modifier `crates/rustwarden-core/`.** Ce crate est le framework "
"partagé. Toute extension passe par :"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:27
msgid ""
"Des **wrappers** côté `gitrust-core` (services qui délèguent au framework)"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:28
msgid "Des **trait impls** (`RustwardenHooks` dans `gitrust-hooks`)"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:29
msgid ""
"Des **extensions** via les mécanismes d'injection Axum (`Extension`, `State`)"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:31
msgid "Aucun contournement en cours"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:33
msgid ""
"Tous les anciens contournements (entités directes, hash manuels) ont été "
"remplacés par les services du framework suite à la mise à jour du 2026-03-26."
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:35
msgid "Ajouter une fonctionnalité nécessitant un service framework absent"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:37
msgid "Si un service nécessaire n'existe pas dans rustwarden-core :"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:39
msgid ""
"Implémenter le service côté `gitrust-core` en réutilisant les primitives du "
"framework (ex: `PasswordService::hash_password` pour le hashage)"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:40
msgid ""
"Si la fonctionnalité est générique et bénéficierait au framework lui-même, "
"ouvrir une issue ou une PR upstream sur le dépôt rustwarden-core"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:41
msgid ""
"Ne pas dupliquer la logique d'auth, de session, ou de JWT — ces domaines "
"appartiennent exclusivement au framework"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:43
msgid "Pattern d'extension via hooks"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:45
msgid ""
"Les hooks (`gitrust-hooks/src/lib.rs`) implémentent `RustwardenHooks` et "
"sont injectés dans le routeur Axum au démarrage :"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:48
msgid "// Dans main.rs\n"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:49
msgid ""
"// Passé via .merge_routes(app_routes(hooks))\n"
"// Puis disponible via axum::Extension dans les handlers\n"
msgstr ""

#: src/developer_manual/how-to/contribuer-a-rustwarden.md:54
msgid ""
"Pour réagir à un nouvel événement du framework, ajouter la méthode "
"correspondante dans l'impl `RustwardenHooks` de `gitrust-hooks`, sans "
"toucher au code du framework qui émet l'événement."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:1
msgid "Architecture par crates"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:3
msgid ""
"Référence structurelle de gitrust : crates, modules, routes, dépendances et "
"composants CI."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:5
msgid "Dépendances entre crates"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:7
msgid ""
"```mermaid\n"
"graph LR\n"
"    RW[\"rustwarden-core\"]\n"
"\n"
"    Git[\"gitrust-git\"]\n"
"    Core[\"gitrust-core\"]\n"
"    Hooks[\"gitrust-hooks\"]\n"
"    SSH[\"gitrust-ssh\"]\n"
"    Web[\"gitrust-web\"]\n"
"    Bin[\"gitrust (binaire)\"]\n"
"\n"
"    Core --> RW\n"
"    Git -.->|\"indépendant<br/>(git2, tokio)\"| RW\n"
"\n"
"    Hooks --> Core\n"
"    Hooks --> RW\n"
"\n"
"    SSH --> Core\n"
"    SSH --> Git\n"
"\n"
"    Web --> Core\n"
"    Web --> Git\n"
"    Web -.->|\"CI pages\"| Git\n"
"\n"
"    Bin --> Core\n"
"    Bin --> Git\n"
"    Bin --> SSH\n"
"    Bin --> Web\n"
"    Bin --> Hooks\n"
"    Bin --> RW\n"
"\n"
"    subgraph \"Externes CI (Phase 5b)\"\n"
"        Dagger[\"Dagger CLI\"]\n"
"        CiEng[\"ci-engine (Python)\"]\n"
"        Syft[\"Syft\"]\n"
"        DTrack[\"Dependency-Track\"]\n"
"    end\n"
"\n"
"    Core -.->|\"CiWorker<br/>sous-processus\"| Dagger\n"
"    Dagger -.-> CiEng\n"
"    Core -.-> Syft\n"
"    Syft -.-> DTrack\n"
"```"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:53
msgid "Crates — Responsabilités"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:55
msgid "gitrust-core"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:57
msgid ""
"Cœur métier. Ne dépend que de rustwarden-core et des crates Rust standards."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:59
#: src/developer_manual/reference/architecture-crates.md:74
#: src/developer_manual/reference/architecture-crates.md:142
msgid "Module"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:61
msgid "`config`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:61
msgid "`GitrustConfig::from_env()` — ports SSH, chemin repos, limites"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:62
msgid "`error`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:62
msgid "`GitrustError` — erreurs domaine Git + `IntoResponse` HTTP"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:63
msgid "`roles`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:63
msgid "`enum Role { Reader, Developer, Maintainer, Owner }` avec `Ord`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:64
msgid "`types`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:64
msgid "Newtypes validés : `RepoSlug`, `TeamSlug`, `Fingerprint`, `TokenHash`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:65
msgid "`models/`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:65
msgid ""
"Entités SeaORM : repository, ssh_key, team, team_member, "
"team_repository_access, ci_pipeline, ci_job, ci_log, ci_config, ci_variable"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:66
msgid "`migrations/`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:66
msgid "Migrations SeaORM (tables gitrust) combinées avec les migrations core"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:67
msgid "`services/`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:67
msgid ""
"`SshKeyService`, `RepositoryService`, `TeamService`, `AccessService`, "
"`CiService`, `CiVariableService`, `CiDetectionService`, `CiWorker`, "
"`NotificationService`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:68
msgid "`dto/`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:68
msgid "Structures d'entrée/sortie pour les services"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:70
msgid "gitrust-git"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:72
msgid ""
"Opérations Git sur le système de fichiers. Utilise `git2` (libgit2). Pas de "
"dépendance vers la base de données."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:76
msgid "`errors`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:76
msgid "`enum GitError` (Git, RepoNotFound, RefNotFound, PathTraversal, ...)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:77
msgid "`bare_repo`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:77
msgid "Init, open, delete, exists + validation chemin canonique sous base"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:78
msgid "`branch` / `tag`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:78
msgid "Listing branches (BranchInfo) et tags (TagInfo, annotated/lightweight)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:79
msgid "`reference`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:79
msgid "resolve_ref (branch -> tag -> SHA -> revparse)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:80
msgid "`tree_browser`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:80
msgid "list_tree (dirs first, sorted), TreeEntry, EntryKind"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:81
msgid "`blob_reader`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:81
msgid "read_blob -> Text/Binary, détection binaire (null bytes)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:82
msgid "`commit_log`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:82
msgid "list_commits (paginé), find_commit, CommitInfo"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:83
msgid "`readme`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:83
msgid "find_readme (README.md > README > readme.md > ...)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:84
msgid "`pack_protocol`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:84
msgid "advertise_refs, serve_pack (async, git-upload-pack/git-receive-pack)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:86
msgid "gitrust-ssh"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:88
msgid "Serveur SSH basé sur `russh`. Authentification par clé publique."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:90
msgid "Module (prévu)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:92
msgid "`server`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:92
msgid "Démarrage, génération clé hôte Ed25519"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:93
msgid "`auth`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:93
msgid "Authentification par fingerprint -> SshKeyService"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:94
msgid "`session`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:94
msgid "Handler SSH (exec, shell)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:95
msgid "`command_handler`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:95
msgid "Parsing `git-upload-pack`/`git-receive-pack`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:97
msgid "gitrust-web"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:99
msgid ""
"Interface web SSR (Server-Side Rendering) avec Askama (templates compilés) + "
"HTMX (interactions dynamiques). Fonctionne en mode `headless()` : les pages "
"UI du framework (`rustwarden-ui`) ne sont pas montées, gitrust-web "
"réimplémente toutes les pages avec un design spécifique (sidebar "
"contextuelle, navigation Git, DaisyUI)."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:101
msgid "**Architecture des routes :**"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:135
msgid ""
"Les routes API du framework sont montées via `framework_api_routes()` dans "
"`routes.rs`. Elles sont utilisées par :"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:136
msgid "Les liens dans les emails (vérification, reset password)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:137
msgid "Le refresh token (rotation JWT, session longue durée)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:138
msgid "L'accès programmatique (GET /me, POST /logout)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:140
msgid ""
"Les pages SSR et les routes API coexistent : les formulaires HTML soumettent "
"aux handlers gitrust (SSR), tandis que les services framework génèrent des "
"liens vers les routes API."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:144
msgid "`routes.rs`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:144
msgid ""
"Routeur principal : framework API + API REST Gitrust + pages SSR + fichiers "
"statiques"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:145
msgid "`handlers/`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:145
msgid "Handlers Axum SSR (un fichier par domaine) + handlers API JSON"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:146
msgid "`templates.rs`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:146
msgid "Structs Askama + SidebarContext + RepoNav"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:147
msgid "`helpers.rs`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:147
msgid "require_auth, require_admin, sidebar\\_\\*, resolve_repo_access"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:148
msgid "`templates/`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:148
msgid "Templates HTML (Askama, extends base.html)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:149
msgid "`static_files.rs`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:149
msgid "ServeDir pour /static"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:151
msgid "gitrust-hooks"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:153
msgid ""
"Implémentation de `RustwardenHooks` pour réagir aux événements du framework. "
"Les hooks sont injectés dans le routeur Axum via `Arc<dyn RustwardenHooks>` "
"+ `axum::Extension` (dans `main.rs`)."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:155
msgid "Hook"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:157
msgid "`on_user_registered`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:157
msgid "Crée le répertoire utilisateur sur le FS (anti path-traversal)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:158
msgid "`on_user_deleted`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:158
msgid "Supprime le répertoire utilisateur + bare repos sur le FS"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:159
msgid "`on_resource_shared`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:159
#: src/developer_manual/reference/architecture-crates.md:160
msgid "Audit log si resource_type = \"repository\""
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:160
msgid "`on_resource_unshared`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:166
msgid ""
"Système de notification à deux canaux : **in-app** (SSE temps réel + page) "
"et **email** (worker SMTP du framework)."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:182
msgid ""
"Les préférences de notification sont par utilisateur (email on/off par type "
"d'événement)."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:186
msgid "CI/CD — Modes et composants"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:188
msgid "Système CI hybride à deux niveaux, activé via `CI_ENABLED=true`."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:190
msgid "Modes"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:192
msgid "Mode"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:192
msgid "Détection"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:192
msgid "Exécution"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:194
msgid "**Easy**"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:194
msgid "`.gitrust-ci.yml` à la racine du repo"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:194
msgid "Module Dagger Python générique (`ci-engine`) interprète le YAML"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:195
msgid "**Power**"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:195
msgid "`.dagger/` à la racine du repo"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:195
msgid "`dagger call -m .dagger/` exécute le module utilisateur directement"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:196
msgid "Aucun"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:196
msgid "Ni l'un ni l'autre"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:196
msgid "Pas de CI pour ce repo"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:198
msgid "Architecture CI"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:233
msgid "Composants externes (tous optionnels sauf Dagger)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:235
msgid "Composant"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:235
msgid "Variable de contrôle"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:237
msgid "Dagger Engine"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:237
msgid "Exécution des pipelines dans des containers isolés"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:238
msgid "ci-engine (Python)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:238
msgid "Moteur générique pour Easy Mode"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:238
msgid "`CI_DAGGER_MODULE_PATH`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:239
msgid "Syft"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:239
msgid "Génération SBOM CycloneDX"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:239
msgid "`CI_SBOM_ENABLED`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:240
msgid "Dependency-Track"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:240
msgid "Analyse de vulnérabilités sur les SBOM"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:240
msgid "`CI_DTRACK_ENABLED`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:242
msgid "Variables et secrets CI"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:244
msgid ""
"Héritage **team → repo** : les variables définies au niveau team sont "
"partagées entre tous les repos de l'équipe. Le repo peut surcharger une clé "
"team avec sa propre valeur. Les secrets sont chiffrés en base (AES-256-GCM) "
"et masqués dans les logs (`***`)."
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:248
msgid "Sécurité (ANSSI PA-074)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:250
msgid "Directive"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:250
msgid "Scope"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:252
msgid "`#![forbid(unsafe_code)]`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:252
msgid "gitrust-core, gitrust-web, gitrust-hooks"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:253
msgid "`#![deny(unsafe_code)]`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:253
msgid "gitrust-git, gitrust-ssh (FFI libgit2/russh)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:254
msgid "`deny(clippy::unwrap_used, expect_used, panic)`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:254
#: src/developer_manual/reference/architecture-crates.md:255
#: src/developer_manual/reference/architecture-crates.md:256
msgid "Tous les crates"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:255
msgid "`deny(clippy::indexing_slicing)`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:256
msgid "`deny(clippy::mem_forget)`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:257
msgid "`Zeroize` on drop"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:257
msgid "`TokenHash` (ANSSI R23)"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:258
msgid "RSA minimum 4096 bits"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:258
msgid "`SshKeyService`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:259
msgid "Path traversal validation"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:259
msgid "`RepositoryService`, `gitrust-git`"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:260
msgid "Slug validation + noms réservés"
msgstr ""

#: src/developer_manual/reference/architecture-crates.md:260
msgid "`RepoSlug`, `TeamSlug`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:1
msgid "Règles QA & conformité ANSSI"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:3
msgid ""
"Ce document définit les règles de qualité et de sécurité applicables à tout "
"le projet gitrust. Chaque lot doit satisfaire ces règles avant merge."
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:7
msgid "1. Gates de compilation obligatoires"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:9
msgid "Toute modification doit passer ces 4 gates sans erreur :"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:11
#: src/developer_manual/reference/regles-qa-anssi.md:20
msgid "Gate"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:11
msgid "Commande"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:11
msgid "Critère"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:13
msgid "Formatage"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:13
msgid "`cargo fmt --all -- --check`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:13
msgid "Zéro diff"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:14
msgid "Linting"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:14
msgid "`cargo clippy --workspace -- -D warnings`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:14
msgid "Zéro warning"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:15
msgid "Tests unitaires"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:15
msgid "`cargo test --workspace`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:15
msgid "100% pass"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:16
msgid "Build CSS"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:16
msgid ""
"`npx tailwindcss -i static/css/input.css -o static/css/style.css --minify`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:16
msgid "Si templates modifiés"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:18
msgid "Gates supplémentaires (à mettre en place)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:22
msgid "Audit dépendances"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:22
msgid "`cargo audit`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:22
msgid "Détection CVE dans les deps"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:23
msgid "Licences & bans"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:23
msgid "`cargo deny check`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:23
msgid "Licences compatibles, pas de crate bannie"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:24
msgid "Secrets dans le code"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:24
msgid "Recherche de patterns sensibles"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:24
msgid "Pas de token/mot de passe en dur"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:28
msgid "2. Règles de sécurité (ANSSI PA-074)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:30
msgid "2.1 Lints Rust obligatoires (déjà en place)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:33
msgid "// core, web, hooks\n"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:34
msgid "// git, ssh (FFI nécessaire)\n"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:42
msgid "2.2 Checklist sécurité par feature"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:44
msgid ""
"Avant toute implémentation touchant l'authentification, les secrets ou les "
"permissions, vérifier :"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:46
msgid "**Secrets jamais en clair en base** — hash SHA-256 ou bcrypt"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:47
msgid ""
"**Secrets jamais loggés** — vérifier `tracing::info/debug/warn`, `Display` "
"et `Debug` impls ne révèlent pas le secret"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:48
msgid ""
"**Comparaison constant-time** — `subtle::ConstantTimeEq` pour toute "
"validation de secret (pas de `==` sur des hash)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:49
msgid "**Rate-limiting** — endpoint d'authentification protégé"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:50
msgid "**CSRF** — token valide sur toute action mutante (POST/PUT/DELETE)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:51
msgid ""
"**Ownership vérifiée (anti-IDOR)** — le user ne peut agir que sur ses "
"propres ressources (vérifier `user_id` côté serveur)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:52
msgid "**Expiration obligatoire** — tout token/session a une durée de vie max"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:53
msgid "**Audit log** — création, révocation, utilisation suspecte tracées"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:54
msgid "**Zeroize** — types sensibles implémentent `Zeroize`/`ZeroizeOnDrop`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:55
msgid ""
"**Path traversal** — validation des chemins disque (pas de `..`, `/`, `\\`)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:57
msgid "2.3 Marqueurs SEC-"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:59
msgid ""
"Le code utilise des commentaires `// SEC-XX` pour tracer les décisions de "
"sécurité. Tout nouveau contrôle doit être marqué avec le prochain numéro "
"disponible dans sa catégorie :"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:61
msgid "Préfixe"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:61
#: src/developer_manual/reference/regles-qa-anssi.md:74
msgid "Catégorie"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:63
msgid "SEC-C"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:63
msgid "Cryptographie"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:63
msgid "Timing attack, CSRF, PKCE"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:64
msgid "SEC-H"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:64
msgid "HTTP/Headers"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:64
msgid "X-Forwarded-For, cookies, nonce"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:65
msgid "SEC-L"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:65
msgid "Logique métier"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:65
msgid "Hashing, validation, defaults"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:66
msgid "SEC-M"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:66
msgid "Mémoire/sessions"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:66
msgid "Rate-limit DoS, refresh tokens"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:70
msgid "3. Tests requis par catégorie"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:72
msgid "3.1 Matrice de couverture"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:74
msgid "Quand appliquer"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:76
msgid "**Unitaire**"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:76
msgid "Logique pure (validation, parsing, conversion)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:76
msgid "`RepoSlug::new(\"../evil\")` → erreur"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:77
msgid "**Intégration**"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:77
msgid "Service avec DB (CRUD, contraintes, transactions)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:77
msgid "`PatService::validate` token expiré → None"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:78
msgid "**Handler**"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:78
msgid "Endpoint HTTP (status, redirect, CSRF, auth)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:78
msgid "POST sans CSRF → 403"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:79
msgid "**E2E Playwright**"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:79
msgid "Flow utilisateur complet"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:79
msgid "Créer token → copier → cloner un dépôt"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:80
msgid "**Sécurité négatif**"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:80
msgid "Tout bypass imaginable"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:80
msgid "Token user A sur ressource user B → 401"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:82
msgid "3.2 Règles de tests"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:84
msgid ""
"**Tests d'intégration sur vraie DB** — pas de mocks pour la couche "
"persistence (les mocks masquent les bugs de migration)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:85
msgid ""
"**Tests négatifs obligatoires** — pour chaque chemin heureux, tester au "
"moins : input invalide, non-authentifié, non-autorisé, expiré, révoqué"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:86
msgid "**Tests E2E en français** — cohérent avec l'UI (locale `fr-FR`)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:87
msgid ""
"**Pas de `sleep()` dans les tests** — utiliser des retry/poll avec timeout"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:88
msgid ""
"**Données de test isolées** — chaque test crée ses propres données (pas de "
"dépendance sur l'ordre d'exécution)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:92
msgid "4. Règles de code"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:94
msgid "4.1 Framework boundary"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:96
msgid "**Ne jamais modifier** `crates/rustwarden-core/`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:97
msgid ""
"Réutiliser les services framework avant d'implémenter (auth, users, "
"sessions, ResourceService, i18n, middleware)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:98
msgid "Si un service manque, l'étendre côté gitrust (wrappers, trait impls)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:100
msgid "4.2 Assets"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:102
msgid "**Zéro CDN** — tous les CSS/JS servis depuis `static/`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:103
msgid "La CSP du framework bloque les domaines externes"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:105
msgid "4.3 Gestion d'erreurs"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:107
msgid "`GitrustError` avec `IntoResponse` pour le mapping HTTP"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:108
msgid "Pas de `.unwrap()` / `.expect()` / `panic!()` / `[index]`"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:109
msgid "Errors utilisateur : messages génériques (pas de leak d'info interne)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:111
msgid "4.4 Validation aux frontières"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:113
msgid "Valider les inputs utilisateur (formulaires, query params, headers)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:114
msgid "Ne pas re-valider entre services internes"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:115
msgid ""
"Newtypes avec validation à la construction (`RepoSlug`, `TeamSlug`, "
"`Fingerprint`, `TokenHash`)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:119
msgid "5. Checklist pré-merge"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:121
msgid "Avant chaque merge de lot :"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:123
msgid "`cargo fmt --all -- --check` passe"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:124
msgid "`cargo clippy --workspace -- -D warnings` passe"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:125
msgid "`cargo test --workspace` — tous les tests passent"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:126
msgid "Tests E2E Playwright passent (`npm run test:e2e`)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:127
msgid "CSS rebuild si templates modifiés"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:128
msgid "Aucun secret en clair dans le code ou les logs"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:129
msgid "Checklist sécurité §2.2 validée (si applicable)"
msgstr ""

#: src/developer_manual/reference/regles-qa-anssi.md:130
msgid "Pas de modification dans `crates/rustwarden-core/`"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:3
msgid ""
"Gitrust est une plateforme d'hébergement Git auto-hébergée construite sur le "
"framework **rustwarden-core**. L'application expose deux points d'entrée "
"réseau (HTTP + SSH) et persiste ses données dans PostgreSQL."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:7
msgid ""
"```mermaid\n"
"graph TB\n"
"    subgraph Clients\n"
"        Browser[\"Navigateur Web\"]\n"
"        GitCLI[\"Git CLI (ssh/https)\"]\n"
"    end\n"
"\n"
"    subgraph \"Gitrust Binary (src/main.rs)\"\n"
"        Main[\"main()\"]\n"
"    end\n"
"\n"
"    subgraph \"Crates Gitrust\"\n"
"        Web[\"gitrust-web<br/><i>Routes HTTP, templates,<br/>handlers Axum</"
"i>\"]\n"
"        SSH[\"gitrust-ssh<br/><i>Serveur SSH (russh),<br/>auth par clé, "
"sessions</i>\"]\n"
"        Hooks[\"gitrust-hooks<br/><i>impl RustwardenHooks<br/"
">(on_user_registered, ...)</i>\"]\n"
"        Core[\"gitrust-core<br/><i>Models, services, migrations,<br/>rôles, "
"types, DTOs</i>\"]\n"
"        Git[\"gitrust-git<br/><i>Bare repos, tree browser,<br/>pack protocol "
"(git2)</i>\"]\n"
"    end\n"
"\n"
"    subgraph \"Framework\"\n"
"        RW[\"rustwarden-core<br/><i>Auth, users, JWT, sessions,<br/"
">ResourceService, i18n</i>\"]\n"
"    end\n"
"\n"
"    subgraph \"Stockage\"\n"
"        PG[(PostgreSQL)]\n"
"        FS[(\"Système de fichiers<br/>bare repos .git\")]\n"
"    end\n"
"\n"
"    subgraph \"CI/CD (optionnel)\"\n"
"        CiWorker[\"CiWorker<br/><i>tokio::spawn, mpsc,<br/>sous-processus "
"Dagger</i>\"]\n"
"        Dagger[\"Dagger Engine<br/><i>Containers isolés,<br/>cache, "
"exécution</i>\"]\n"
"        CiEngine[\"ci-engine<br/><i>Module Dagger Python<br/>(Easy Mode)</"
"i>\"]\n"
"        Syft[\"Syft (optionnel)<br/><i>Génération SBOM<br/>CycloneDX</i>\"]\n"
"        DTrack[\"Dependency-Track<br/>(optionnel)<br/><i>Analyse "
"vulnérabilités</i>\"]\n"
"    end\n"
"\n"
"    Browser -->|HTTP :4000| Web\n"
"    GitCLI -->|SSH :2222| SSH\n"
"    GitCLI -->|HTTPS :4000| Web\n"
"\n"
"    Main --> Web\n"
"    Main --> SSH\n"
"    Main --> Hooks\n"
"    Main -.->|\"si CI_ENABLED\"| CiWorker\n"
"\n"
"    Web --> Core\n"
"    Web --> Git\n"
"    SSH --> Core\n"
"    SSH --> Git\n"
"    Hooks --> Core\n"
"\n"
"    Core --> RW\n"
"    Core --> PG\n"
"    Git --> FS\n"
"\n"
"    CiWorker --> Core\n"
"    CiWorker -->|\"dagger call\"| Dagger\n"
"    Dagger -->|\"Easy Mode\"| CiEngine\n"
"    Dagger -->|\"Power Mode\"| FS\n"
"    CiWorker -.->|\"si CI_SBOM_ENABLED\"| Syft\n"
"    Syft -.->|\"si CI_DTRACK_ENABLED\"| DTrack\n"
"```"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:72
msgid "Démarrage de l'application"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:74
msgid ""
"Le diagramme suivant détaille la séquence d'initialisation depuis `main()` "
"jusqu'au démarrage des serveurs HTTP et SSH."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:120
msgid "Principes de conception"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:122
msgid "Séparation framework / métier gitrust"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:124
msgid ""
"Gitrust est construit **au-dessus** de rustwarden-core, un framework Rust "
"d'authentification et de gestion d'utilisateurs. Cette séparation est "
"intentionnelle :"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:126
msgid ""
"**rustwarden-core** gère : auth JWT, sessions, users, roles génériques, "
"i18n, SMTP, OAuth, audit log générique."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:127
msgid ""
"**gitrust-core** gère : tout ce qui est spécifique à la forge Git — dépôts, "
"clés SSH, équipes, permissions RBAC à 4 niveaux, CI, import de dépôts."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:129
msgid ""
"La règle fondamentale : **ne jamais modifier `crates/rustwarden-core/`**. "
"Toute extension passe par des wrappers, des hooks (`RustwardenHooks`) ou des "
"traits implémentés côté gitrust."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:131
msgid "Mode headless"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:133
msgid ""
"gitrust-web opère en mode `headless()` : les pages UI standard de rustwarden "
"(login, register, settings) sont **désactivées** et réimplémentées "
"entièrement dans `gitrust-web/templates/`. Cela permet un design cohérent "
"(sidebar Git, DaisyUI) sans compromis avec l'UI générique du framework."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:135
msgid "SSR + HTMX, zéro CDN"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:137
msgid ""
"L'interface est rendue côté serveur via Askama (templates Rust compilés). "
"HTMX gère les interactions dynamiques (mises à jour partielles de page, SSE "
"pour les notifications et les logs CI). Aucun asset externe : tout CSS/JS "
"est servi depuis `static/` — imposé par la Content Security Policy du "
"framework."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:139
msgid "Bare repos sur le système de fichiers"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:141
msgid ""
"gitrust-git est **découplé de la base de données**. Les opérations Git "
"(navigation d'arbre, lecture de blobs, pack protocol) travaillent "
"directement sur les bare repos (`{GIT_REPOS_BASE_PATH}/{owner}/{slug}.git/`) "
"via libgit2. La base ne stocke que les métadonnées (nom, description, "
"visibilité, ownership). Ce découplage permet de remplacer ou tester gitrust-"
"git indépendamment."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:143
msgid "CI hybride : Dagger comme abstraction d'exécution"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:145
msgid ""
"Plutôt que d'implémenter un runner CI from scratch, gitrust délègue "
"l'exécution à **Dagger**, qui garantit l'isolation (containers), la "
"reproductibilité (cache) et la portabilité (local ou runner distant via "
"SSH+rsync). Le `CiWorker` est une tâche Tokio dans le processus principal — "
"pas un daemon séparé — ce qui simplifie le déploiement (un seul binaire)."
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:149
msgid "Pour aller plus loin"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:151
msgid ""
"Référence structurelle complète (tables de modules, routes, dépendances) : "
"`developer_manual/reference/architecture-crates.md`"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:152
msgid ""
"Diagrammes de séquence détaillés (clone SSH, push, permissions) : "
"`developer_manual/explanation/flux-requetes.md`"
msgstr ""

#: src/developer_manual/explanation/vue-ensemble-architecture.md:153
msgid ""
"Règles de code et gates QA : `developer_manual/reference/regles-qa-anssi.md`"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:3
msgid ""
"Diagrammes de séquence couvrant les opérations principales de gitrust : "
"création de dépôt, clone et push SSH, enregistrement de clé SSH, résolution "
"des permissions, navigation web, inscription utilisateur."
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:5
msgid "1. Création d'un dépôt (Web)"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:7
msgid ""
"```mermaid\n"
"sequenceDiagram\n"
"    actor User as Utilisateur\n"
"    participant Web as gitrust-web\n"
"    participant RepoSvc as RepositoryService\n"
"    participant ResSvc as ResourceService\n"
"    participant DB as PostgreSQL\n"
"    participant Git as gitrust-git\n"
"    participant FS as Système de fichiers\n"
"\n"
"    User->>Web: POST /new {name, description}\n"
"    Web->>Web: Extraire user_id (session JWT)\n"
"\n"
"    Web->>RepoSvc: create(db, owner_id, username, base_path, input)\n"
"    RepoSvc->>RepoSvc: RepoSlug::from_name(input.name)\n"
"    RepoSvc->>DB: SELECT ... WHERE owner_id AND slug\n"
"    DB-->>RepoSvc: None (pas de doublon)\n"
"\n"
"    RepoSvc->>RepoSvc: compute_disk_path(base, owner, slug)\n"
"    Note over RepoSvc: Validation anti path-traversal\n"
"\n"
"    RepoSvc->>ResSvc: register(db, \"repository\", repo_id, owner_id)\n"
"    ResSvc->>DB: INSERT INTO resources\n"
"    DB-->>ResSvc: Ok\n"
"\n"
"    RepoSvc->>DB: INSERT INTO repositories\n"
"    DB-->>RepoSvc: repository::Model\n"
"\n"
"    RepoSvc-->>Web: RepositoryOutput\n"
"\n"
"    Web->>Git: BareRepo::init(disk_path)\n"
"    Git->>FS: git init --bare\n"
"    FS-->>Git: Ok\n"
"    Git-->>Web: Ok\n"
"\n"
"    Web-->>User: 302 Redirect /{owner}/{slug}\n"
"```"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:45
msgid "2. Clone SSH (git clone)"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:47
msgid ""
"```mermaid\n"
"sequenceDiagram\n"
"    actor Dev as Développeur\n"
"    participant Client as Git CLI\n"
"    participant SSH as gitrust-ssh\n"
"    participant Auth as SshKeyService\n"
"    participant Access as AccessService\n"
"    participant Git as gitrust-git\n"
"    participant DB as PostgreSQL\n"
"    participant FS as Bare repo (.git)\n"
"\n"
"    Dev->>Client: git clone ssh://git@host:2222/alice/my-repo.git\n"
"    Client->>SSH: Connexion TCP :2222\n"
"    SSH-->>Client: Banner SSH + échange clés\n"
"\n"
"    Client->>SSH: Auth publickey (signature)\n"
"    SSH->>Auth: find_by_fingerprint(db, fingerprint)\n"
"    Auth->>DB: SELECT FROM ssh_keys WHERE fingerprint = ?\n"
"    DB-->>Auth: ssh_key::Model {user_id, ...}\n"
"    Auth-->>SSH: user_id\n"
"\n"
"    SSH->>Auth: update_last_used(db, key_id)\n"
"    Auth->>DB: UPDATE ssh_keys SET last_used_at = now()\n"
"\n"
"    SSH-->>Client: Auth OK\n"
"\n"
"    Client->>SSH: exec \"git-upload-pack 'alice/my-repo.git'\"\n"
"    SSH->>SSH: CommandHandler::parse(\"git-upload-pack alice/my-repo.git\")\n"
"    Note over SSH: Extraction owner=alice, repo=my-repo\n"
"\n"
"    SSH->>Access: effective_role(db, user_id, repo_id)\n"
"    Access->>DB: Check ownership + shares + teams\n"
"    DB-->>Access: Role::Developer\n"
"    Access-->>SSH: can_read = true\n"
"\n"
"    SSH->>Git: pack_protocol::advertise_refs(repo_path)\n"
"    Git->>FS: Lecture refs\n"
"    FS-->>Git: refs/heads/main, ...\n"
"    Git-->>SSH: advertise output\n"
"\n"
"    SSH-->>Client: refs advertisement\n"
"    Client->>SSH: want/have negotiation\n"
"\n"
"    SSH->>Git: pack_protocol::serve_pack(repo_path, wants, haves)\n"
"    Git->>FS: Pack objects\n"
"    FS-->>Git: pack data\n"
"    Git-->>SSH: pack stream\n"
"\n"
"    SSH-->>Client: pack data\n"
"    Client-->>Dev: Dépôt cloné avec succès\n"
"```"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:99
msgid "3. Push SSH (git push)"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:101
msgid ""
"```mermaid\n"
"sequenceDiagram\n"
"    actor Dev as Développeur\n"
"    participant Client as Git CLI\n"
"    participant SSH as gitrust-ssh\n"
"    participant Access as AccessService\n"
"    participant Git as gitrust-git\n"
"    participant Hooks as gitrust-hooks\n"
"    participant DB as PostgreSQL\n"
"    participant FS as Bare repo (.git)\n"
"\n"
"    Note over Client,SSH: Session SSH déjà authentifiée\n"
"\n"
"    Client->>SSH: exec \"git-receive-pack 'alice/my-repo.git'\"\n"
"    SSH->>SSH: CommandHandler::parse(...)\n"
"    Note over SSH: Extraction owner=alice, repo=my-repo\n"
"\n"
"    SSH->>Access: effective_role(db, user_id, repo_id)\n"
"    Access->>DB: Check ownership + shares + teams\n"
"    DB-->>Access: Role::Developer\n"
"    Access-->>SSH: can_push = true\n"
"\n"
"    SSH->>Git: pack_protocol::advertise_refs(repo_path)\n"
"    Git->>FS: Lecture refs\n"
"    Git-->>SSH: refs advertisement\n"
"\n"
"    SSH-->>Client: refs\n"
"    Client->>SSH: pack data + commands\n"
"\n"
"    SSH->>Git: pack_protocol::serve_pack(repo_path, receive-pack)\n"
"    Git->>FS: Écriture objets + update refs\n"
"    FS-->>Git: Ok\n"
"    Git-->>SSH: Ok\n"
"\n"
"    SSH->>DB: UPDATE repositories SET is_empty = false, updated_at = now()\n"
"\n"
"    SSH-->>Client: Push OK\n"
"    Client-->>Dev: Push réussi\n"
"```"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:141
msgid "4. Enregistrement d'une clé SSH"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:174
msgid "5. Résolution des permissions (AccessService)"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:176
msgid ""
"```mermaid\n"
"sequenceDiagram\n"
"    participant Caller as Handler / SSH Session\n"
"    participant AS as AccessService\n"
"    participant RS as ResourceService\n"
"    participant DB as PostgreSQL\n"
"\n"
"    Caller->>AS: effective_role(db, user_id, repo_id)\n"
"\n"
"    AS->>RS: effective_permission(db, user_id, \"repository\", repo_id)\n"
"    RS->>DB: SELECT FROM resources WHERE type AND id\n"
"    DB-->>RS: resource {owner_id, is_public}\n"
"\n"
"    alt user_id == owner_id\n"
"        RS-->>AS: \"owner\"\n"
"    else Share exists\n"
"        RS->>DB: SELECT FROM resource_shares WHERE resource AND user\n"
"        DB-->>RS: share {permission_level}\n"
"        RS-->>AS: permission_level\n"
"    else Resource is public\n"
"        RS-->>AS: \"read\"\n"
"    else No access\n"
"        RS-->>AS: None\n"
"    end\n"
"\n"
"    AS->>AS: Role::from_permission(individual_level)\n"
"\n"
"    AS->>DB: SELECT team_members + team_repository_access<br/>WHERE user_id "
"AND repository_id\n"
"    DB-->>AS: Vec<team_permission>\n"
"\n"
"    AS->>AS: team_role = max(team_permissions)\n"
"    AS->>AS: effective = max(individual_role, team_role)\n"
"\n"
"    AS-->>Caller: Role (Reader / Developer / Maintainer / Owner)\n"
"```"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:212
msgid "6. Navigation dans un dépôt (Web)"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:214
msgid ""
"```mermaid\n"
"sequenceDiagram\n"
"    actor User as Utilisateur\n"
"    participant Web as gitrust-web\n"
"    participant Ext as RepoExtractor\n"
"    participant Access as AccessService\n"
"    participant Git as gitrust-git\n"
"    participant DB as PostgreSQL\n"
"    participant FS as Bare repo\n"
"\n"
"    User->>Web: GET /alice/my-repo/tree/main/src\n"
"    Web->>Ext: RepoContext::extract(owner=alice, repo=my-repo, ref=main, "
"path=src)\n"
"\n"
"    Ext->>DB: SELECT user WHERE username = 'alice'\n"
"    DB-->>Ext: user {id}\n"
"\n"
"    Ext->>DB: SELECT repository WHERE owner_id AND slug\n"
"    DB-->>Ext: repository::Model\n"
"\n"
"    Ext->>Access: effective_role(db, visitor_id, repo_id)\n"
"    Access-->>Ext: Role::Reader\n"
"\n"
"    Ext-->>Web: RepoContext {repo, role, ref, path}\n"
"\n"
"    Web->>Git: tree_browser::list_tree(repo_path, \"main\", \"src\")\n"
"    Git->>FS: Resolve ref main -> commit -> tree -> src/\n"
"    FS-->>Git: Vec<TreeEntry>\n"
"\n"
"    Git-->>Web: entries (fichiers + dossiers)\n"
"\n"
"    Web->>Git: readme::find_readme(repo_path, \"main\", \"src\")\n"
"    Git->>FS: Cherche README.md, README, readme.md\n"
"    FS-->>Git: Option<BlobContent>\n"
"    Git-->>Web: Option<readme_content>\n"
"\n"
"    Web->>Web: Render template tree.html\n"
"    Web-->>User: HTML (arbre + README)\n"
"```"
msgstr ""

#: src/developer_manual/explanation/flux-requetes.md:253
msgid "7. Inscription utilisateur + création répertoire"
msgstr ""

#: src/template/index.md:1
msgid "Bibliothèque de templates gitrust"
msgstr ""

#: src/template/index.md:3
msgid ""
"Bienvenue dans l'atelier gitrust. Chaque fichier ici est **standalone et "
"copiable tel quel** — un fichier, un cas d'usage. Les commentaires internes "
"suffisent à l'adapter. Pour les explications pédagogiques, référez-vous aux "
"manuels qui pointent vers ces templates."
msgstr ""

#: src/template/index.md:5
msgid ""
"**Convention** : copiez le fichier qui correspond à votre cas, adaptez les "
"valeurs marquées `CHANGE_ME`, puis supprimez les commentaires si vous le "
"souhaitez. Ne modifiez pas les fichiers dans ce dépôt — travaillez toujours "
"sur une copie locale."
msgstr ""

#: src/template/index.md:9
msgid "Fichiers d'environnement (`env/`)"
msgstr ""

#: src/template/index.md:11 src/template/index.md:22 src/template/index.md:33
#: src/template/index.md:43 src/template/index.md:52 src/template/index.md:65
#: src/template/index.md:76 src/template/index.md:86
msgid "Cas d'usage"
msgstr ""

#: src/template/index.md:13
msgid "[`env/dev-local.env`](env/dev-local.env)"
msgstr ""

#: src/template/index.md:13
msgid ""
"Instance de développement local sur `localhost:4000` — PostgreSQL local, pas "
"de TLS, debug activé"
msgstr ""

#: src/template/index.md:14
msgid "[`env/production-mono-machine.env`](env/production-mono-machine.env)"
msgstr ""

#: src/template/index.md:14
msgid ""
"Production mono-machine derrière reverse-proxy — PostgreSQL, SMTP, Redis "
"sessions, TLS délégué"
msgstr ""

#: src/template/index.md:15
msgid "[`env/production-ci-heavy.env`](env/production-ci-heavy.env)"
msgstr ""

#: src/template/index.md:15
msgid ""
"Production avec CI runners distants intensifs — tuning pool de connexions, "
"rate limiting ajusté"
msgstr ""

#: src/template/index.md:16
msgid "[`env/tests-e2e.env`](env/tests-e2e.env)"
msgstr ""

#: src/template/index.md:16
msgid ""
"Environnement E2E Playwright — base éphémère, seed de données, SMTP mock"
msgstr ""

#: src/template/index.md:20
msgid "Stacks Docker (`docker/`)"
msgstr ""

#: src/template/index.md:24
msgid ""
"[`docker/docker-compose.minimal.yml`](docker/docker-compose.minimal.yml)"
msgstr ""

#: src/template/index.md:24
msgid ""
"Stack minimale : gitrust + PostgreSQL uniquement — idéale pour l'évaluation "
"et les tutoriels"
msgstr ""

#: src/template/index.md:25
msgid ""
"[`docker/docker-compose.production.yml`](docker/docker-compose.production."
"yml)"
msgstr ""

#: src/template/index.md:25
msgid ""
"Stack production : gitrust + PostgreSQL + Redis sessions + relay SMTP Postfix"
msgstr ""

#: src/template/index.md:26
msgid ""
"[`docker/docker-compose.with-ci-runner.yml`](docker/docker-compose.with-ci-"
"runner.yml)"
msgstr ""

#: src/template/index.md:26
msgid ""
"Stack production + CI runner Dagger en sidecar — pour instances avec builds "
"fréquents"
msgstr ""

#: src/template/index.md:27
msgid "[`docker/podman-quadlet.container`](docker/podman-quadlet.container)"
msgstr ""

#: src/template/index.md:27
msgid ""
"Alternative Podman Quadlet — déploiement rootless systemd-native sans Docker "
"daemon"
msgstr ""

#: src/template/index.md:31
msgid "Reverse-proxy (`reverse-proxy/`)"
msgstr ""

#: src/template/index.md:35
msgid "[`reverse-proxy/nginx-tls.conf`](reverse-proxy/nginx-tls.conf)"
msgstr ""

#: src/template/index.md:35
msgid ""
"Nginx avec TLS Let's Encrypt — virtual host gitrust, headers de sécurité, "
"proxy WebSocket SSE"
msgstr ""

#: src/template/index.md:36
msgid "[`reverse-proxy/caddy-Caddyfile`](reverse-proxy/caddy-Caddyfile)"
msgstr ""

#: src/template/index.md:36
msgid ""
"Caddyfile — TLS automatique, configuration minimale, idéal pour les petites "
"instances"
msgstr ""

#: src/template/index.md:37
msgid ""
"[`reverse-proxy/traefik-dynamic.yml`](reverse-proxy/traefik-dynamic.yml)"
msgstr ""

#: src/template/index.md:37
msgid ""
"Traefik config dynamique — intégration labels Docker, middlewares rate-limit "
"et auth"
msgstr ""

#: src/template/index.md:41
msgid "Systemd (`systemd/`)"
msgstr ""

#: src/template/index.md:45
msgid "[`systemd/gitrust.service`](systemd/gitrust.service)"
msgstr ""

#: src/template/index.md:45
msgid ""
"Service systemd avec hardening AppArmor/seccomp — pour déploiement binaire "
"natif sans Docker"
msgstr ""

#: src/template/index.md:46
msgid "[`systemd/gitrust-backup.timer`](systemd/gitrust-backup.timer)"
msgstr ""

#: src/template/index.md:46
msgid ""
"Timer systemd de sauvegarde quotidienne — déclenche `backup.sh` à 2h00 avec "
"journalisation"
msgstr ""

#: src/template/index.md:50
msgid "Configurations CI (`.gitrust-ci.yml`) (`ci/`)"
msgstr ""

#: src/template/index.md:54
msgid "[`ci/rust.gitrust-ci.yml`](ci/rust.gitrust-ci.yml)"
msgstr ""

#: src/template/index.md:54
msgid ""
"Pipeline CI pour projet Rust — fmt, clippy, test, audit de dépendances, SBOM"
msgstr ""

#: src/template/index.md:55
msgid "[`ci/go.gitrust-ci.yml`](ci/go.gitrust-ci.yml)"
msgstr ""

#: src/template/index.md:55
msgid "Pipeline CI pour projet Go — vet, staticcheck, test, build multi-arch"
msgstr ""

#: src/template/index.md:56
msgid "[`ci/python.gitrust-ci.yml`](ci/python.gitrust-ci.yml)"
msgstr ""

#: src/template/index.md:56
msgid "Pipeline CI pour projet Python — ruff, mypy, pytest, packaging wheel"
msgstr ""

#: src/template/index.md:57
msgid "[`ci/node.gitrust-ci.yml`](ci/node.gitrust-ci.yml)"
msgstr ""

#: src/template/index.md:57
msgid "Pipeline CI pour projet Node.js — ESLint, Vitest, build, audit npm"
msgstr ""

#: src/template/index.md:58
msgid "[`ci/dagger-power-mode/dagger.json`](ci/dagger-power-mode/dagger.json)"
msgstr ""

#: src/template/index.md:58
msgid ""
"Squelette Dagger Power Mode — module Go minimal à étendre pour pipelines "
"complexes"
msgstr ""

#: src/template/index.md:59
msgid "[`ci/dagger-power-mode/main.go`](ci/dagger-power-mode/main.go)"
msgstr ""

#: src/template/index.md:59
msgid "Module Dagger Go — fonctions build/test/publish prêtes à adapter"
msgstr ""

#: src/template/index.md:63
msgid "Scripts de sauvegarde et restauration (`backup/`)"
msgstr ""

#: src/template/index.md:67
msgid "[`backup/backup.sh`](backup/backup.sh)"
msgstr ""

#: src/template/index.md:67
msgid ""
"Sauvegarde complète — `pg_dump` + `rsync` des dépôts bare + copie des clés "
"SSH host"
msgstr ""

#: src/template/index.md:68
msgid "[`backup/restore.sh`](backup/restore.sh)"
msgstr ""

#: src/template/index.md:68
msgid ""
"Restauration complète depuis une archive de sauvegarde — avec vérification "
"d'intégrité"
msgstr ""

#: src/template/index.md:72
msgid "Clients API d'exemple (`api-clients/`)"
msgstr ""

#: src/template/index.md:74
msgid ""
"Ces exemples illustrent l'authentification par Personal Access Token (PAT) "
"et les opérations CRUD de base sur l'API REST gitrust v1."
msgstr ""

#: src/template/index.md:78
msgid ""
"[`api-clients/python-create-repo.py`](api-clients/python-create-repo.py)"
msgstr ""

#: src/template/index.md:78
msgid "Client Python — créer un dépôt via l'API v1 avec `httpx` et PAT"
msgstr ""

#: src/template/index.md:79
msgid "[`api-clients/rust-list-repos.rs`](api-clients/rust-list-repos.rs)"
msgstr ""

#: src/template/index.md:79
msgid "Client Rust — lister les dépôts avec pagination via `reqwest` et PAT"
msgstr ""

#: src/template/index.md:80
msgid "[`api-clients/curl-pat-auth.sh`](api-clients/curl-pat-auth.sh)"
msgstr ""

#: src/template/index.md:80
msgid ""
"Shell curl — exemples d'authentification PAT, GET/POST/DELETE sur les "
"endpoints principaux"
msgstr ""

#: src/template/index.md:84
msgid "Scripts de migration (`migration/`)"
msgstr ""

#: src/template/index.md:88
msgid "[`migration/from-gitea.sh`](migration/from-gitea.sh)"
msgstr ""

#: src/template/index.md:88
msgid ""
"Import en masse depuis Gitea — dépôts, membres, issues via le worker "
"d'import gitrust"
msgstr ""

#: src/template/index.md:89
msgid "[`migration/from-forgejo.sh`](migration/from-forgejo.sh)"
msgstr ""

#: src/template/index.md:89
msgid ""
"Import en masse depuis Forgejo — même mécanique, adaptée à l'API Forgejo"
msgstr ""

#: src/template/index.md:93
msgid "Comment utiliser ces templates depuis les manuels"
msgstr ""

#: src/template/index.md:95
msgid ""
"Les manuels narratifs pointent vers ces fichiers depuis leurs sections how-"
"to. Par exemple :"
msgstr ""

#: src/template/index.md:97
msgid ""
"`administration_manual/how-to/configurer-smtp.md` → _« Copiez `template/env/"
"production-mono-machine.env` puis... »_"
msgstr ""

#: src/template/index.md:98
msgid ""
"`administration_manual/tutorials/01-installation-docker.md` → _« La stack "
"s'appuie sur `template/docker/docker-compose.minimal.yml` »_"
msgstr ""

#: src/template/index.md:99
msgid ""
"`developer_manual/how-to/implementer-endpoint-api.md` → _« Testez avec "
"`template/api-clients/curl-pat-auth.sh` »_"
msgstr ""

#: src/template/index.md:101
msgid ""
"Les templates ne contiennent pas d'explication pédagogique — tout le "
"contexte se trouve dans les manuels."
msgstr ""