Add ROADMAP.md and gitfed-tui -set-public/-set-private for v1.0.0
ROADMAP.md separates what's rejected outright (SSO, PAT auth, a federation directory) from what's deferred on complexity/priority grounds (in-browser conflict resolution, inline diff comments, alternate merge strategies, scheduled backups, enforced NetworkPolicy) from open candidates for later — grounded in decisions already made during development, not new speculation. Linked from both READMEs. gitfed-tui gains -set-public/-set-private <repo>: flips visibility non-interactively over `kubectl exec`, so that one operation is scriptable without driving the TUI's keystrokes against a live instance.
5 files changed
+115 −0
M
CHANGELOG.md
+6 −0
M
README.fr.md
+1 −0
M
README.md
+1 −0
A
ROADMAP.md
+84 −0
M
cmd/gitfed-tui/main.go
+23 −0
CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## 1.0.0
+
+First stable release. Federated SSH-certificate identity, per-repo/per-role ACLs, a self-service web UI (repo browser, commit history and detail, merge requests with review and a real server-side merge, pinned repos, federated notifications), anonymous read-only HTTPS clone for public repos, and a documented backup/restore procedure — see `README.md` for the full picture and `ROADMAP.md` for what was deliberately left out and why.
+
+Also adds `gitfed-tui -set-public <repo>` / `-set-private <repo>`: a non-interactive way to flip a repo's visibility over `kubectl exec`, without driving the interactive TUI's keystrokes against a live instance.
+
## 0.10.3
- A file path outside the repo tree (e.g. `?path=../../../etc/passwd`) returned a raw 500 instead of the usual 404 — git itself already rejects it (`relative path syntax can't be used outside working tree`), so nothing was ever exposed, but gitfed didn't recognize that error as "not found" like it does every other one. Found while re-checking the older file-browsing code for the same bug class as 0.10.1's fix.
README.fr.md
@@ -68,6 +68,7 @@ instance en fonctionnement.
| [`docs/security/AUDIT-2026-07-29.md`](docs/security/AUDIT-2026-07-29.md) | Audit de suivi couvrant le clone HTTPS anonyme, les notifications fédérées et les dépôts épinglés ajoutés depuis. |
| [`docs/security/AUDIT-2026-07-29b.md`](docs/security/AUDIT-2026-07-29b.md) | Audit des merge requests — a trouvé et corrigé une faille critique non authentifiée (écriture de fichier arbitraire via des hash de commit / noms de branche forgés), plus deux correctifs de moindre sévérité. |
| [`DESIGN.md`](DESIGN.md) | Le document de conception d'origine — le « pourquoi » derrière l'architecture, écrit avant le début de l'implémentation. |
+| [`ROADMAP.md`](ROADMAP.md) | Ce qui a été volontairement laissé de côté pour la V1 et pourquoi, ce qui est rejeté purement et simplement, et ce qui pourrait venir ensuite. |
| [`CHANGELOG.md`](CHANGELOG.md) | Historique des versions (également servi sur `/changelog` dans l'interface web). |
| [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) | Chaque dépendance Go et sa licence. |
README.md
@@ -64,6 +64,7 @@ instance.
| [`docs/security/AUDIT-2026-07-29.md`](docs/security/AUDIT-2026-07-29.md) *(French)* | Follow-up audit covering the anonymous HTTPS clone, federated notifications and pinned repos added afterward. |
| [`docs/security/AUDIT-2026-07-29b.md`](docs/security/AUDIT-2026-07-29b.md) *(French)* | Audit of merge requests — found and fixed a critical, unauthenticated argument-injection bug (arbitrary file write via crafted commit hashes/branch names), plus two lower-severity fixes. |
| [`DESIGN.md`](DESIGN.md) *(French)* | The original design rationale — the "why" behind the architecture, written before implementation started. |
+| [`ROADMAP.md`](ROADMAP.md) *(French)* | What was deliberately left out of V1 and why, versus what's rejected outright versus what might come later. |
| [`CHANGELOG.md`](CHANGELOG.md) | Version history (also served at `/changelog` in the web UI). |
| [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) | Every Go dependency and its license. |
ROADMAP.md
@@ -0,0 +1,84 @@
+# Feuille de route
+
+Ce document liste ce qui a été volontairement laissé de côté pour la V1,
+pourquoi, et ce qui pourrait venir ensuite — pas un engagement de
+calendrier, juste une trace de l'état des décisions pour ne pas avoir à
+re-débattre les mêmes questions plus tard. Voir [`DESIGN.md`](DESIGN.md)
+pour le rationnel d'origine, et les entrées `## X.Y.Z` de
+[`CHANGELOG.md`](CHANGELOG.md) pour ce qui a réellement été livré.
+
+---
+
+## 1. Rejeté, pas juste reporté
+
+Ces points ont été explicitement discutés et écartés — les rouvrir
+demande une vraie raison nouvelle, pas juste "ce serait bien d'avoir".
+
+- **SSO / connexion fédérée pour l'interface web.** Le modèle d'identité
+ de gitfed (certificats SSH courte durée, voir
+ [`docs/HOW_IT_WORKS.md`](docs/HOW_IT_WORKS.md) §2) couvre déjà l'accès
+ git ; ajouter du SSO pour le web ouvrirait une deuxième surface
+ d'authentification fédérée à maintenir et à faire confiance, pour un
+ gain limité puisque le mot de passe web n'ouvre déjà qu'une session
+ opaque sans droit git (§4 du même document).
+- **Authentification par jeton (PAT) pour le clone HTTPS.** Le clone HTTPS
+ anonyme couvre déjà le seul cas légitime (lecture publique sans
+ compte) ; un jeton ajouterait un deuxième mécanisme d'écriture par HTTP
+ à côté de SSH, contraire au principe "une seule porte à surveiller"
+ ([`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §6-7).
+- **Annuaire / découverte publique d'instances fédérées.** Le modèle
+ retenu est que chaque personne ajoute elle-même l'URL des instances
+ auxquelles elle a accès — un annuaire centralisé recréerait exactement
+ le point de couplage fort que la fédération pair-à-pair est censée
+ éviter.
+
+## 2. Reporté — complexité ou priorité, pas un refus de principe
+
+- **Résolution de conflit dans le navigateur.** Les merge requests
+ détectent les conflits et bloquent la fusion avec la liste précise des
+ fichiers concernés, mais la résolution se fait en local (`git pull` +
+ fusion + push) — un éditeur de conflit web est un morceau nettement
+ plus gros, à faire seulement si le besoin se confirme à l'usage.
+- **Commentaires de diff en ligne (par ligne).** Les merge requests n'ont
+ qu'un fil de discussion général pour l'instant — des commentaires
+ ancrés sur une ligne précise demandent de gérer leur position au fil
+ des nouveaux push (rebase, force-push, etc.), volontairement pas fait
+ dans la première version.
+- **Stratégies de fusion alternatives (squash, rebase, fast-forward
+ seul).** Le bouton "Fusionner" ne fait qu'un commit de fusion classique
+ (`--no-ff`) systématiquement. Réévaluer si l'historique en devient trop
+ bruyant en pratique.
+- **Sauvegardes planifiées automatiquement.** `deploy/backup.sh` existe
+ et fonctionne, mais rien ne le déclenche tout seul — c'est à
+ l'opérateur de le brancher sur un cron/timer. Pas de stockage hors-site
+ (S3 ou équivalent) prévu non plus pour l'instant.
+- **`NetworkPolicy` réellement appliquée.** Le manifeste existe
+ (`deploy/k8s/networkpolicy.yaml`) mais k3s + flannel (la configuration
+ par défaut de ce cluster) ne l'applique pas — nécessiterait de changer
+ de CNI (Cilium, Calico...), pas fait tant que ce cluster reste
+ mono-tenant.
+- **Minuterie de renouvellement pour `gitfed-renew-cert`.** L'outil existe
+ côté client, mais aucun exemple de timer systemd/cron n'est fourni —
+ chacun le met en place lui-même pour l'instant.
+
+## 3. Candidats pour plus tard, sans priorité arrêtée
+
+Des idées qui reviendraient naturellement si l'usage le justifie, mais
+qui ne sont pas des manques identifiés aujourd'hui :
+
+- Recherche de code (pas seulement par nom de dépôt/sujet).
+- Intégration CI / webhooks sortants sur push ou fusion.
+- ACL par équipe/organisation, en plus de l'ACL par personne actuelle.
+- Import/miroir depuis un dépôt externe (GitHub, etc.).
+
+## 4. Ce qui ne changera probablement jamais
+
+Rappel du principe directeur (voir les deux README) : **gitfed n'essaie
+pas de rivaliser avec GitHub ou GitLab sur le nombre de fonctionnalités.**
+Le modèle d'identité fédérée est le sujet ; l'interface web existe pour le
+rendre utilisable au quotidien, pas pour cocher toutes les cases d'un
+forge complet. Un fork inter-dépôts (pull request cross-repo façon
+GitHub) n'est notamment pas prévu : le modèle actuel est un dépôt partagé
+avec des collaborateurs à accès explicite, pas un graphe de forks — ça
+resterait vrai même si des organisations/équipes étaient ajoutées un
+jour.
cmd/gitfed-tui/main.go
@@ -21,6 +21,8 @@ import (
func main() {
configPath := flag.String("config", "gitfed.json", "path to instance config file")
+ setPublic := flag.String("set-public", "", "non-interactive: make <repo> public and exit, skipping the TUI")
+ setPrivate := flag.String("set-private", "", "non-interactive: make <repo> private and exit, skipping the TUI")
flag.Parse()
cfg, err := config.Load(*configPath)
@@ -37,6 +39,27 @@ func main() {
}
defer closeFn()
+ // -set-public/-set-private exist so this one operation is scriptable
+ // (e.g. over `kubectl exec`) without driving the interactive TUI's
+ // keystrokes against a live instance — every other admin action still
+ // goes through the TUI on purpose.
+ if *setPublic != "" || *setPrivate != "" {
+ if *setPublic != "" && *setPrivate != "" {
+ fmt.Fprintln(os.Stderr, "gitfed-tui: pass only one of -set-public / -set-private")
+ os.Exit(1)
+ }
+ repo, public := *setPublic, true
+ if *setPrivate != "" {
+ repo, public = *setPrivate, false
+ }
+ if err := ops.SetRepoPublic(repo, public); err != nil {
+ fmt.Fprintf(os.Stderr, "gitfed-tui: set-public %s: %v\n", repo, err)
+ os.Exit(1)
+ }
+ fmt.Printf("%s is now %s\n", repo, map[bool]string{true: "public", false: "private"}[public])
+ return
+ }
+
p := tea.NewProgram(newModel(ops, cfg.Domain, mode), tea.WithAltScreen())
if _, err := p.Run(); err != nil {
fmt.Fprintf(os.Stderr, "gitfed-tui: %v\n", err)