mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-16 19:59:56 +02:00
La façade sert /api/projects quand LOKI_PROJECTS=rust (expérimental ; le Go reste le défaut) : liste avec discussions, pages et trackers comptés, création (slug translittéré et unique, index amorcé), renommage, description, suppression (discussions, trackers et mémoire du projet, actif réassigné, dernier projet indestructible) et bascule, refusées pendant une génération. Le projet actif passe toujours par le Go, qui en garde une copie en RAM. Les discussions sont à qui tient la conversation : la façade bascule et supprime elle-même quand elle la tient, sinon le Go garde /internal/v1/project/switch et /internal/v1/project/drop-convs (facade_projects.go). Parité : parity_projects_test.go tire du Go 40 appels sur une base amorcée (pages, discussions, trackers piégés), avec le registre, l'actif, memory/, les trackers et l'index après chacun, rejoués par tests/projects_api.rs contre un faux Go qui bascule et supprime comme le vrai ; bascule et suppression par la façade de bout en bout ; TestFacadeProjets côté Go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
78 lines
2.5 KiB
Go
78 lines
2.5 KiB
Go
package loki
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// facade_projects.go — hub des projets tenu par la façade Rust
|
|
// (LOKI_PROJECTS=rust, lot 18 de la migration ; expérimental, le Go reste le
|
|
// défaut) : liste avec ses comptes, création, renommage, description,
|
|
// suppression, bascule (/api/projects).
|
|
//
|
|
// Le registre reste dans la base (state/projects) et la mémoire de chaque
|
|
// projet dans memory/<slug>. Le projet actif passe toujours par le Go
|
|
// (/internal/v1/project/activate), qui en garde une copie en RAM. Quand le Go
|
|
// tient la conversation, ce qui la touche reste ici :
|
|
//
|
|
// - la bascule : discussion du projet quitté enregistrée, la plus récente
|
|
// du projet rejoint ouverte (/internal/v1/project/switch) ;
|
|
// - les discussions d'un projet supprimé (/internal/v1/project/drop-convs).
|
|
//
|
|
// Quand la façade tient la conversation, elle fait les deux elle-même.
|
|
|
|
const facadeProjectsEnv = "LOKI_PROJECTS"
|
|
|
|
// facadeProjects : la façade tient-elle le hub des projets ?
|
|
func facadeProjects() bool {
|
|
return strings.EqualFold(strings.TrimSpace(os.Getenv(facadeProjectsEnv)), "rust") &&
|
|
facadeAddr() != "" && internalToken() != ""
|
|
}
|
|
|
|
// facadeProjectsRoutes : les routes que la façade sert alors (projects_api.rs).
|
|
var facadeProjectsRoutes = map[string]bool{
|
|
"/api/projects": true,
|
|
}
|
|
|
|
// handleInternalProjectSwitch : POST {slug} → 204, ou 400/409 + {error}.
|
|
func handleInternalProjectSwitch(w http.ResponseWriter, r *http.Request) {
|
|
var in struct {
|
|
Slug string `json:"slug"`
|
|
}
|
|
if !readInternalJSON(w, r, &in) {
|
|
return
|
|
}
|
|
if conv.isGenerating() {
|
|
sendJSON(w, http.StatusConflict, map[string]any{"error": "une génération est en cours"})
|
|
return
|
|
}
|
|
if err := projectSwitch(strings.TrimSpace(in.Slug)); err != nil {
|
|
sendJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
// handleInternalProjectDropConvs : POST {slug} → 200 {dropped} — supprime les
|
|
// discussions du projet, comme deleteProject quand le Go tient la conversation.
|
|
func handleInternalProjectDropConvs(w http.ResponseWriter, r *http.Request) {
|
|
var in struct {
|
|
Slug string `json:"slug"`
|
|
}
|
|
if !readInternalJSON(w, r, &in) {
|
|
return
|
|
}
|
|
if conv.isGenerating() {
|
|
sendJSON(w, http.StatusConflict, map[string]any{"error": "une génération est en cours"})
|
|
return
|
|
}
|
|
n := 0
|
|
for _, m := range convIndexForProject(strings.TrimSpace(in.Slug)) {
|
|
if convDelete(m.ID) == nil {
|
|
n++
|
|
}
|
|
}
|
|
sendJSON(w, http.StatusOK, map[string]any{"dropped": n})
|
|
}
|