Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
147 lines
3.6 KiB
Go
147 lines
3.6 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
fleetai "crypto-miner-server/internal/ai"
|
|
"crypto-miner-server/internal/clearance"
|
|
"crypto-miner-server/internal/models"
|
|
)
|
|
|
|
const stuckHostFailedTierThreshold = 14
|
|
|
|
// ClearanceManager returns the hub's session clearance tracker.
|
|
func (h *WSHub) ClearanceManager() *ClearanceManager {
|
|
if h == nil {
|
|
return nil
|
|
}
|
|
return h.clearance
|
|
}
|
|
|
|
// ClearanceManager tracks per-agent session clearance and broadcasts changes.
|
|
type ClearanceManager struct {
|
|
hub *WSHub
|
|
mu sync.RWMutex
|
|
// agentClearance holds live session clearance keyed by agent ID.
|
|
agentClearance map[string]int
|
|
}
|
|
|
|
func NewClearanceManager(hub *WSHub) *ClearanceManager {
|
|
return &ClearanceManager{
|
|
hub: hub,
|
|
agentClearance: make(map[string]int),
|
|
}
|
|
}
|
|
|
|
// InitAgent sets baseline clearance when an agent connects.
|
|
func (m *ClearanceManager) InitAgent(agentID string, agent *models.Agent) int {
|
|
if m == nil {
|
|
return clearance.DefaultClearance(agent)
|
|
}
|
|
level := clearance.DefaultClearance(agent)
|
|
m.mu.Lock()
|
|
m.agentClearance[agentID] = level
|
|
m.mu.Unlock()
|
|
// Baseline clearance is included in auth_response; push only on elevation.
|
|
return level
|
|
}
|
|
|
|
// RemoveAgent drops session clearance state.
|
|
func (m *ClearanceManager) RemoveAgent(agentID string) {
|
|
if m == nil {
|
|
return
|
|
}
|
|
m.mu.Lock()
|
|
delete(m.agentClearance, agentID)
|
|
m.mu.Unlock()
|
|
}
|
|
|
|
// Level returns the current session clearance for an agent.
|
|
func (m *ClearanceManager) Level(agentID string) int {
|
|
if m == nil {
|
|
return clearance.L0
|
|
}
|
|
m.mu.RLock()
|
|
level, ok := m.agentClearance[agentID]
|
|
m.mu.RUnlock()
|
|
if ok {
|
|
return level
|
|
}
|
|
if m.hub != nil && m.hub.db != nil {
|
|
if agent, err := m.hub.db.GetAgent(agentID); err == nil && agent != nil {
|
|
return clearance.DefaultClearance(agent)
|
|
}
|
|
}
|
|
return clearance.L0
|
|
}
|
|
|
|
// RequestElevation raises clearance when needed and notifies dashboards.
|
|
func (m *ClearanceManager) RequestElevation(agentID string, toLevel int, reason, source string) (int, error) {
|
|
if m == nil {
|
|
return clearance.L0, nil
|
|
}
|
|
current := m.Level(agentID)
|
|
newLevel, err := clearance.RequestElevation(m.hub.db, agentID, current, toLevel, reason, source)
|
|
if err != nil {
|
|
return current, err
|
|
}
|
|
if newLevel <= current {
|
|
return current, nil
|
|
}
|
|
m.mu.Lock()
|
|
m.agentClearance[agentID] = newLevel
|
|
m.mu.Unlock()
|
|
m.pushToAgent(agentID, newLevel)
|
|
m.broadcastElevation(agentID, current, newLevel, reason, source)
|
|
return newLevel, nil
|
|
}
|
|
|
|
func (m *ClearanceManager) pushToAgent(agentID string, level int) {
|
|
if m == nil || m.hub == nil {
|
|
return
|
|
}
|
|
_ = m.hub.SendToAgent(agentID, Message{
|
|
Type: "clearance_update",
|
|
Payload: mustMarshal(map[string]interface{}{
|
|
"clearance_level": level,
|
|
}),
|
|
})
|
|
}
|
|
|
|
func (m *ClearanceManager) broadcastElevation(agentID string, fromLevel, toLevel int, reason, source string) {
|
|
if m == nil || m.hub == nil {
|
|
return
|
|
}
|
|
m.hub.broadcastDashboard(Message{
|
|
Type: "clearance_elevated",
|
|
Payload: mustMarshal(map[string]interface{}{
|
|
"agent_id": agentID,
|
|
"from_level": fromLevel,
|
|
"to_level": toLevel,
|
|
"reason": reason,
|
|
"source": source,
|
|
}),
|
|
})
|
|
}
|
|
|
|
// ClearanceGuardExecutor wraps FleetAIExecutor with clearance enforcement.
|
|
type ClearanceGuardExecutor struct {
|
|
Inner *FleetAIExecutor
|
|
Clearance *ClearanceManager
|
|
}
|
|
|
|
func (e *ClearanceGuardExecutor) Execute(agentID string, cmd fleetai.Command) (string, error) {
|
|
if e == nil || e.Inner == nil {
|
|
return "", fmt.Errorf("executor unavailable")
|
|
}
|
|
level := clearance.L0
|
|
if e.Clearance != nil {
|
|
level = e.Clearance.Level(agentID)
|
|
}
|
|
if err := clearance.EnforceClearance(cmd.Type, cmd.Args, level); err != nil {
|
|
return "", err
|
|
}
|
|
return e.Inner.Execute(agentID, cmd)
|
|
}
|