helmd hub: central server på Pi5 + agent-uplink + helmd ctl + web-login
All checks were successful
helmd-image / build (push) Successful in 3m22s
helmd-release / build-release (push) Successful in 4m28s

Hub-läge i samma binär (doc/hub-plan.md): agenter ansluter utåt med
delad agent-nyckel (hub-sektion i config.json), web-/CLI-klienter
loggar in (lokala konton, pbkdf2; Authenticator-interface för LDAP
senare) och styr alla agenters sessioner via proxy + merged SSE.
Webbklienten autodetekterar hub/local via /api/mode. Nya kommandon:
helmd hub [setpass|users|agentkey], helmd ctl (login/agents/sessions/
prompt/screen/answer/events …). Enhetstester + scripts/run-hub-smoke.sh
(15-stegs e2e: hub + agent + ctl).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011KikHkfCiC3yELbsMN8fT9
This commit is contained in:
2026-08-06 23:19:18 +02:00
parent d0b57e8224
commit 77682e91b5
17 changed files with 2411 additions and 37 deletions

View File

@@ -55,6 +55,12 @@ func readJSON(r *http.Request, v interface{}) error {
func (a *API) routes() *http.ServeMux {
mux := http.NewServeMux()
// oautentiserad läges-detektering: webbklienten är samma SPA för
// lokal helmd och hub och avgör läget med det här svaret
mux.HandleFunc("GET /api/mode", func(w http.ResponseWriter, r *http.Request) {
jsonOut(w, 200, map[string]string{"mode": "local", "version": version})
})
mux.HandleFunc("GET /api/health", a.auth(func(w http.ResponseWriter, r *http.Request) {
jsonOut(w, 200, map[string]interface{}{
"ok": true, "version": version, "sessions": len(a.mgr.List()),
@@ -357,6 +363,9 @@ func serve(cfg *Config) error {
}
api := &API{cfg: cfg, mgr: mgr, shares: shares, ntfy: ntfy}
mux := api.routes()
if cfg.Hub.Enabled && cfg.Hub.URL != "" {
startUplink(cfg, mux, mgr)
}
mountWeb(mux)
log.Printf("helmd %s lyssnar på http://%s (token i %s)", version, cfg.Listen, cfg.path)
return http.ListenAndServe(cfg.Listen, mux)