package atlas import ( "strings" ) // Fleet gossip kinds — shard DHT advertisements relayed fleet-wide (not LAN-only). const ( FleetGossipHaveShard = "have_shard" FleetGossipHealthy = "healthy" FleetGossipKnowNode = "know_node" ) // FleetGossipRecord is one peer advertisement in the fleet torrent DHT. type FleetGossipRecord struct { Kind string `json:"kind"` AgentID string `json:"agent_id,omitempty"` Subnet string `json:"subnet,omitempty"` Token string `json:"token,omitempty"` ShardIndex int `json:"shard_index,omitempty"` ShardHash string `json:"shard_hash,omitempty"` TargetAgentID string `json:"target_agent_id,omitempty"` Healthy bool `json:"healthy,omitempty"` FetchURL string `json:"fetch_url,omitempty"` } // NormalizeFleetGossipRecord validates and trims one fleet gossip record. func NormalizeFleetGossipRecord(r FleetGossipRecord) (FleetGossipRecord, bool) { r.Kind = strings.TrimSpace(strings.ToLower(r.Kind)) r.AgentID = strings.TrimSpace(r.AgentID) r.Subnet = strings.TrimSpace(r.Subnet) r.Token = strings.TrimSpace(r.Token) r.ShardHash = strings.TrimSpace(strings.ToLower(r.ShardHash)) r.TargetAgentID = strings.TrimSpace(r.TargetAgentID) r.FetchURL = strings.TrimSpace(r.FetchURL) switch r.Kind { case FleetGossipHaveShard: if r.AgentID == "" || r.Token == "" || r.ShardHash == "" { return FleetGossipRecord{}, false } case FleetGossipHealthy: if r.AgentID == "" { return FleetGossipRecord{}, false } case FleetGossipKnowNode: if r.AgentID == "" || r.TargetAgentID == "" { return FleetGossipRecord{}, false } default: return FleetGossipRecord{}, false } return r, true } // NormalizeFleetGossipRecords drops invalid records while preserving order. func NormalizeFleetGossipRecords(in []FleetGossipRecord) []FleetGossipRecord { if len(in) == 0 { return nil } out := make([]FleetGossipRecord, 0, len(in)) for _, r := range in { if norm, ok := NormalizeFleetGossipRecord(r); ok { out = append(out, norm) } } return out }