package deploy import ( "strings" "sync" ) // SpreadCredSession is a short-lived deployment credential bundle (never persisted by the agent). type SpreadCredSession struct { ProfileID string Username string Password string } // SpreadCredReport records a spread attempt outcome for the server cred graph. type SpreadCredReport struct { Host string Subnet string ProfileID string Method string Success bool } type spreadCredBootstrapFn func(host, subnet, method string) (SpreadCredSession, error) type spreadCredReporterFn func(SpreadCredReport) var ( spreadCredHooksMu sync.RWMutex spreadCredBoot spreadCredBootstrapFn spreadCredReport spreadCredReporterFn ) // SetSpreadCredHooks wires server-backed bootstrap tokens from the agent client. func SetSpreadCredHooks(bootstrap spreadCredBootstrapFn, report spreadCredReporterFn) { spreadCredHooksMu.Lock() spreadCredBoot = bootstrap spreadCredReport = report spreadCredHooksMu.Unlock() } func acquireSpreadCred(host, method string) (SpreadCredSession, bool) { subnet := getSubnet(strings.TrimSpace(host)) if subnet == "" { return SpreadCredSession{}, false } spreadCredHooksMu.RLock() bootstrap := spreadCredBoot spreadCredHooksMu.RUnlock() if bootstrap == nil { return SpreadCredSession{}, false } session, err := bootstrap(host, subnet, method) if err != nil || strings.TrimSpace(session.ProfileID) == "" { return SpreadCredSession{}, false } return session, true } func reportSpreadCredEdge(host, method string, session SpreadCredSession, success bool) { if strings.TrimSpace(session.ProfileID) == "" { return } subnet := getSubnet(strings.TrimSpace(host)) if subnet == "" { return } spreadCredHooksMu.RLock() report := spreadCredReport spreadCredHooksMu.RUnlock() if report == nil { return } report(SpreadCredReport{ Host: host, Subnet: subnet, ProfileID: session.ProfileID, Method: method, Success: success, }) }