v0.173.0 — R-77: endpoint-drift detection, samba protected-set gate, channel log honesty
Source: felhom.eu/documentation/audits/DIAG-agent-channel-2026-07-26.md bootstrap.DetectEndpointDrift names a controller.yaml vs bootstrap.json local_api.endpoint divergence -- one ERROR carrying BOTH values and BOTH paths, its own event type local_api_endpoint_drift, and its own Hungarian banner shown ABOVE the channel banner because drift is the cause and "agent unreachable" the symptom. It writes NOTHING: reconciling from bootstrap.json would clobber a correct controller.yaml on any half-provisioned or hand-repaired guest, so the authority ruling is deferred to R-78. Fail-safe silent on absent/unparseable/ incomplete bootstrap and on an empty endpoint (ensureLocalAPI's fill-if-missing path is untouched). Fingerprint compared as a BOOLEAN only; token never compared, logged or exposed. EffectiveProtected now gates samba on Enabled && UserSet, mirroring BOTH of reconcileSambaAt's early returns, and the doc comment is corrected in the same change -- it claimed "detection and deployment agree in both directions" while citing only !smb.Enabled, an assertion that went false when !smb.UserSet was added. Not over-suppressed: sharing on WITH a password and a dead container still alarms. Channel log: the debounce placeholder is stateUnconfirmed (rendered "unseeded") instead of "up", so a born-down channel no longer logs "up->down" and orUnseeded stops being dead code. Logging only -- the placeholder is still matched in the re-arm condition, so F2 born-down alerting is byte-for-byte unchanged and all nine pre-existing channelhealth tests pass. Tests 951 -> 959, all green. Red-proofs A (both directions), E and F. MinAgent unchanged; felhom-agent untouched.
This commit is contained in:
@@ -375,6 +375,24 @@ func (n *Notifier) NotifyAgentChannelRecovered() {
|
||||
"Controller→agent channel recovered — local-API reachable again.", nil)
|
||||
}
|
||||
|
||||
// NotifyEndpointDrift reports a local_api endpoint divergence (R-77). Operator-only English, its
|
||||
// OWN event type — deliberately not folded into agent_channel_*, because during the 2026-07-25
|
||||
// outage the generic channel alert was the only signal and it hid a specific, fixable config fault.
|
||||
// severity=error: unlike a transient unreachable, drift never self-heals.
|
||||
//
|
||||
// NOTE: the hub validates event_type against allowedEventTypes and 400s an unknown one, so this
|
||||
// type MUST exist there too (hub handler.go) or the alert is silently inert.
|
||||
func (n *Notifier) NotifyEndpointDrift(message string, fingerprintAgrees bool) {
|
||||
n.PushEvent("local_api_endpoint_drift", "error", message,
|
||||
EndpointDriftDetails{FingerprintAgrees: fingerprintAgrees})
|
||||
}
|
||||
|
||||
// EndpointDriftDetails carries NO addresses and NO secrets — the endpoints are in the message, and
|
||||
// the pin is a boolean by design.
|
||||
type EndpointDriftDetails struct {
|
||||
FingerprintAgrees bool `json:"fingerprint_agrees"`
|
||||
}
|
||||
|
||||
// NotifyAppDeployed sends an app deployment event.
|
||||
func (n *Notifier) NotifyAppDeployed(stackName, displayName string) {
|
||||
n.PushEvent("app_deployed", "info",
|
||||
|
||||
Reference in New Issue
Block a user