geenforce: a PC that has gone quiet stops reading as healthy

A report records how ONE cycle went. Nothing ages it, so a PC that stops
reporting keeps the status of its last good cycle: switch a machine off after a
clean run and it shows 'ok' indefinitely. One had been offline more than a day
and still read 'ok'.

Silence is a different fact from the last cycle's outcome, so it is computed
separately rather than by rewriting the stored status. receivedat - the server's
own clock, not anything a client asserts - is compared against
geenforce_reportstaleminutes, default 30, which is roughly two missed cycles at
the usual cadence. Set it to 0 to turn the check off.

In the table 'stale' takes the badge, because a status from a machine that has
not spoken since is not evidence of anything. What it last reported stays in the
tooltip with the time it was heard. The stored status is untouched: it is still
a true record of that cycle, just not proof the PC is alive.

A site whose scope enforces less often than the threshold will read stale while
healthy, which is what the setting is for.
This commit is contained in:
cproudlock
2026-08-13 09:28:37 -04:00
parent 20a95013ad
commit 962979d483
4 changed files with 169 additions and 2 deletions

View File

@@ -141,6 +141,26 @@ class GeEnforcePlugin(BasePlugin):
},
]
def get_settings_defaults(self) -> List[Dict]:
"""How long a PC may go quiet before the fleet table calls it stale."""
return [
{
'key': 'geenforce_reportstaleminutes',
'value': '30',
'valuetype': 'integer',
'category': 'geenforce',
'description': 'Minutes without an enforcement report before a '
'PC is shown as stale. A report records how the '
'LAST cycle went, so a PC that stops reporting '
'keeps whatever status it last sent - it reads '
'as healthy while it is switched off. Set to 0 '
'to disable the check.',
# Server-side only: nothing on a PC reads this, so it stays off
# the public settings surface.
'public': False,
},
]
def init_app(self, app: Flask, db_instance) -> None:
logger.info(f"GE-Enforce plugin initialized (v{self.meta.version})")