Release validation: tests green, USB pack, fleet UX and API hardening.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Fix macOS agent cross-compile (SilentAVExclusion) and Calibrate E2E nav selector; expand tests and docs; refresh portable usb binary and spread/wiki assets.
This commit is contained in:
@@ -106,12 +106,7 @@ func (h *PathTracerHandler) expireSessions() {
|
||||
h.mu.Unlock()
|
||||
for _, sess := range expired {
|
||||
log.Printf("[pathtrace] session %s expired after %s", sess.ID[:8], pathTraceSessionTTL)
|
||||
for _, hop := range sess.Hops {
|
||||
_ = h.hub.writeAgentJSON(hop.AgentID, Message{
|
||||
Type: "command",
|
||||
Payload: mustMarshal(map[string]interface{}{"action": "wg_teardown"}),
|
||||
})
|
||||
}
|
||||
h.teardownHops(sess.Hops)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +126,23 @@ func (h *PathTracerHandler) Start(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "max 3 hops supported", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
seen := make(map[string]bool, len(req.AgentIDs))
|
||||
for _, id := range req.AgentIDs {
|
||||
id = strings.TrimSpace(id)
|
||||
if id == "" {
|
||||
http.Error(w, "agent_ids required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if seen[id] {
|
||||
http.Error(w, "duplicate agent_ids", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
seen[id] = true
|
||||
if !h.hub.isAgentConnected(id) {
|
||||
http.Error(w, "agent "+id[:min(8, len(id))]+" not connected", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
clientPriv, clientPub, err := generateServerWGKeyPair()
|
||||
if err != nil {
|
||||
@@ -146,11 +158,14 @@ func (h *PathTracerHandler) Start(w http.ResponseWriter, r *http.Request) {
|
||||
clientPubKey: clientPub,
|
||||
}
|
||||
|
||||
// Build hops with placeholder names (agent name lookup below).
|
||||
for i, id := range req.AgentIDs {
|
||||
agentName := fmt.Sprintf("hop-%d", i+1)
|
||||
if ag, err := h.hub.db.GetAgent(id); err == nil && strings.TrimSpace(ag.Name) != "" {
|
||||
agentName = ag.Name
|
||||
}
|
||||
sess.Hops = append(sess.Hops, &HopInfo{
|
||||
AgentID: id,
|
||||
AgentName: fmt.Sprintf("hop-%d", i+1),
|
||||
AgentName: agentName,
|
||||
LocalAddr: fmt.Sprintf("10.66.0.%d/24", i+2), // .2, .3, .4
|
||||
Port: 51820,
|
||||
Status: HopPending,
|
||||
@@ -239,13 +254,7 @@ func (h *PathTracerHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Tell all agents to tear down.
|
||||
for _, hop := range sess.Hops {
|
||||
_ = h.hub.writeAgentJSON(hop.AgentID, Message{
|
||||
Type: "command",
|
||||
Payload: mustMarshal(map[string]interface{}{"action": "wg_teardown"}),
|
||||
})
|
||||
}
|
||||
h.teardownHops(sess.Hops)
|
||||
|
||||
h.mu.Lock()
|
||||
delete(h.sessions, id)
|
||||
@@ -326,6 +335,10 @@ func (h *PathTracerHandler) orchestrate(sess *TraceSession) {
|
||||
r.hop.Status = HopFailed
|
||||
r.hop.Error = r.err
|
||||
sess.Error = "hop " + r.hop.AgentID[:8] + " failed: " + r.err
|
||||
} else if strings.TrimSpace(r.pub) == "" || strings.TrimSpace(r.ip) == "" {
|
||||
r.hop.Status = HopFailed
|
||||
r.hop.Error = "missing public key or external IP"
|
||||
sess.Error = "hop " + r.hop.AgentID[:8] + " failed: missing public key or external IP"
|
||||
} else {
|
||||
r.hop.PublicKey = r.pub
|
||||
r.hop.ExternalIP = r.ip
|
||||
@@ -347,6 +360,7 @@ func (h *PathTracerHandler) orchestrate(sess *TraceSession) {
|
||||
h.mu.Unlock()
|
||||
if anyFailed {
|
||||
log.Printf("[pathtrace] session %s: setup failed", sess.ID[:8])
|
||||
h.teardownHops(sess.Hops)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -430,11 +444,24 @@ func (h *PathTracerHandler) orchestrate(sess *TraceSession) {
|
||||
if allReady {
|
||||
sess.Ready = true
|
||||
}
|
||||
hops := sess.Hops
|
||||
h.mu.Unlock()
|
||||
if !allReady {
|
||||
h.teardownHops(hops)
|
||||
}
|
||||
|
||||
log.Printf("[pathtrace] session %s: orchestration complete, ready=%v", sess.ID[:8], allReady)
|
||||
}
|
||||
|
||||
func (h *PathTracerHandler) teardownHops(hops []*HopInfo) {
|
||||
for _, hop := range hops {
|
||||
_ = h.hub.writeAgentJSON(hop.AgentID, Message{
|
||||
Type: "command",
|
||||
Payload: mustMarshal(map[string]interface{}{"action": "wg_teardown"}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// buildHopPeers returns WireGuard peer entries for hop index i in the chain.
|
||||
func buildHopPeers(sess *TraceSession, i int) []map[string]interface{} {
|
||||
var peers []map[string]interface{}
|
||||
|
||||
Reference in New Issue
Block a user