From 53ab971fe461de36b80896caf3f75febd84e3cf7 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Sat, 11 Jul 2026 13:59:23 +0200 Subject: [PATCH] feat: debug-log the capability-gate verdict per add + SupportState.String() Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6 --- controller/internal/agentapi/features.go | 12 ++++++++++++ controller/internal/web/netstorage_handlers.go | 13 ++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/controller/internal/agentapi/features.go b/controller/internal/agentapi/features.go index d0dd335..84c6b7f 100644 --- a/controller/internal/agentapi/features.go +++ b/controller/internal/agentapi/features.go @@ -35,6 +35,18 @@ const ( SupportNo ) +// String returns the state's wire/template vocabulary: "yes" | "no" | "unknown". +func (s SupportState) String() string { + switch s { + case SupportYes: + return "yes" + case SupportNo: + return "no" + default: + return "unknown" + } +} + // SupportProber is the minimal agent surface a probe needs. *Client satisfies it, and so does the // web layer's netAgent seam — tests inject fakes there. type SupportProber interface { diff --git a/controller/internal/web/netstorage_handlers.go b/controller/internal/web/netstorage_handlers.go index 0afdec9..3a8c1bc 100644 --- a/controller/internal/web/netstorage_handlers.go +++ b/controller/internal/web/netstorage_handlers.go @@ -37,14 +37,7 @@ func (s *Server) netAddSupport() string { } ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() - switch s.netFeatures.Supports(ctx, agent, agentapi.FeatureNetstorageVerify) { - case agentapi.SupportYes: - return "yes" - case agentapi.SupportNo: - return "no" - default: - return "unknown" - } + return s.netFeatures.Supports(ctx, agent, agentapi.FeatureNetstorageVerify).String() } // networkStorageItem is the UI row: the registered descriptor + live per-share health from the agent. @@ -121,7 +114,9 @@ func (s *Server) handleNetStorageAdd(w http.ResponseWriter, r *http.Request) { // instead of failing mid-pipeline in `verifying` with a misleading rollback. Runs BEFORE the // single-flight claim (a refused add must not consume the slot). SupportUnknown passes: a down // agent speaks through the existing agent-error paths, never as "too old". - if s.netFeatures.Supports(r.Context(), agent, agentapi.FeatureNetstorageVerify) == agentapi.SupportNo { + support := s.netFeatures.Supports(r.Context(), agent, agentapi.FeatureNetstorageVerify) + s.logger.Printf("[DEBUG] [web] netstorage add %q capability gate: %s=%s", name, agentapi.FeatureNetstorageVerify, support) + if support == agentapi.SupportNo { s.logger.Printf("[WARN] [web] netstorage add %q refused: agent predates %s (probe 404)", name, agentapi.FeatureNetstorageVerify) writeDiskJSON(w, http.StatusPreconditionFailed, false, netAddOutdatedMsg, map[string]any{"code": "agent_outdated"}) return