Skip to content

fix: revoke readiness after repeated periodic validation failures (#162) - #197

Open
miyunari wants to merge 1 commit into
mainfrom
fix/162-revoke-readiness-on-failure
Open

miyunari wants to merge 1 commit into
mainfrom
fix/162-revoke-readiness-on-failure

Conversation

@miyunari

@miyunari miyunari commented Nov 4, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #162. In continuous mode the validation agent only ever set ready = true and had no path back to not-ready, so once a pod became ready it kept serving traffic regardless of later periodic validation results. A model that was tampered with or swapped on the volume after startup was detected and logged on the next periodic check — but the pod stayed in the Service endpoints. Startup is fail-closed; steady state was fail-open forever.

What changed

  • New CRD field continuousValidation.failureThreshold — the number of consecutive failed periodic re-validations tolerated before the pod is marked not-ready and removed from the Service endpoints. A later successful validation restores readiness.
  • The pod webhook translates the field into an internal --max-consecutive-failures flag on the validation agent (both native-sidecar and legacy-sidecar paths). Users only interact with the CRD field; the flag is an implementation detail.
  • The periodic loop was extracted from main() into continuousValidationLoop + a pure handleValidationResult helper so the readiness logic is unit-tested — cmd/validation-agent/ had no tests before.
  • GetConfigHash now includes failureThreshold so configuration-drift detection notices changes.
  • README + examples/continuous-validation.yaml updated.

Semantics

failureThreshold Behavior
0 Never revoke readiness once ready — the previous fail-open behavior
1 (default) Fail-closed: a single failed periodic validation removes the pod from rotation
N > 1 Revoke readiness only after N consecutive failures (tolerates transient blips)

⚠️ Behavior change on upgrade

The default of 1 is fail-closed. An existing continuous-validation deployment whose model starts failing re-validation (including a transient failure, e.g. a brief volume/network hiccup) will now be removed from rotation, where previously it stayed ready. Operators who want the old behavior can set failureThreshold: 0; those who want to tolerate blips can set a higher value.

This default was chosen deliberately as security-first — the whole point of continuous validation is to stop serving a model that no longer validates.

Testing

  • make test — all packages pass (new unit tests for the readiness logic + loop, new webhook arg assertions, race-clean).
  • make lint — no new findings beyond the repo's pre-existing baseline.

Notes

The issue author (who proposed this direction) suggested two separate flags (--fail-closed + --max-consecutive-failures). This PR collapses them into a single failureThreshold integer where 0 = off, which covers both cases with one user-facing knob.

🤖 Generated with Claude Code

@miyunari
miyunari force-pushed the fix/162-revoke-readiness-on-failure branch from 9596edd to 7765e42 Compare November 4, 2026 16:39
@miyunari
miyunari requested review from knrc and sampras343 November 6, 2026 19:40
In continuous mode the validation agent only ever set `ready = true` and
never revoked it, so a model that started failing re-validation after the
initial success kept serving traffic indefinitely. A tampered or swapped
model was detected and logged, but the pod stayed in the Service endpoints.

Add a `failureThreshold` field to `continuousValidation` that controls how
many consecutive periodic failures are tolerated before the agent marks
itself not-ready, which removes the pod from the Service until a later
validation succeeds again. The webhook translates the field into an
internal `--max-consecutive-failures` flag on the validation agent; users
only ever interact with the CRD field.

- `failureThreshold: 0` keeps the previous fail-open behavior (never revoke).
- `failureThreshold: 1` (default) is fail-closed: a single failure removes
  the pod from rotation.
- Higher values tolerate transient blips before revoking.

The periodic loop is extracted from main() into `continuousValidationLoop`
plus a pure `handleValidationResult` helper so the readiness logic is unit
tested (the package had no tests before).

BREAKING: the default of 1 means an existing continuous-validation
deployment whose model starts failing re-validation will now be removed
from rotation, where before it stayed ready. Set `failureThreshold: 0` to
keep the old behavior.

Fixes #162

Signed-off-by: Nina Bongartz <pninak@web.de>
@miyunari
miyunari force-pushed the fix/162-revoke-readiness-on-failure branch from 7765e42 to a4f00ec Compare November 6, 2026 19:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Continuous mode never revokes readiness after a failed periodic validation

1 participant