Every EU AI Act control I track moves through the same five states. None of them is "done": satisfied, evidence_missing, evidence_stale, pending_review, waived.
The third one is the state most compliance tooling skips. A control isn't just satisfied or not. The evidence behind it can expire.
Opencomplai's control register attaches a freshness TTL to every piece of evidence backing a control. So a bias-testing result from eight months ago, against a model you have since retrained three times, doesn't silently keep counting as satisfied. It ages into evidence_stale and shows up in opencomplai controls status as something that needs a fresh run, not something to rediscover at next year's audit.
It's cache invalidation, applied to legal evidence instead of application data. The hard part was never storing the value. It was knowing when the value you stored stopped being true.
Each control maps to one specific article of the Act, has an owner, and moves through those five states on every CI run. "Are we still compliant" becomes a query against current state, not an annual archaeology project through old spreadsheets.
waived exists on purpose. Sometimes a control genuinely doesn't apply to a system, and pretending otherwise is its own kind of lying.
The full lifecycle, what triggers each transition and what "stale" means for different evidence types, is documented next to the code, not in a whitepaper: github.com/Opencomplai/opencomplai, see the Controls Lifecycle doc and services/evidence-vault.
Top comments (1)
The five states look right to me. What I would push on next is the transition predicates, and
evidence_stale -> satisfiedin particular, since from the description here it fires on "a fresh run happened" without comparing the new evidence to the evidence it replaces. A TTL is a proxy for "the subject may have moved." If you can observe the subject moving directly, the clock is the weaker of the two signals. Your eight-month-old bias result is the easy direction. The hard one is fresh and wrong: a retrain yesterday against a 90-day TTL leaves the control sitting insatisfiedwith evidence that has not expired and is no longer true.Two things I measured on a public append-only ledger I parse end to end. A freshness timestamp on capability declarations advanced 51 times while the declared body stayed byte-for-byte identical, so the clock was reporting the cadence of the re-run job rather than anything about the subject, and a free re-assertion was enough to leave the stale state. The reverse also showed up: the declared content changed and the
versionfield did not move at all, which means a consumer keying its cache on version never refetches.The third number is the one I would hold against
waived. Of 1,552 signed decision records in that ledger, 1,513 carried a verbatim identical reason string, and the structured evidence-id array was empty in 1,551 of them. A required free-text justification that nothing ever queries collapses into one sentence of boilerplate. So a waiver with no expiry and no reconfirmation transition ends up indistinguishable fromsatisfiedwearing a different label, and I would give the waiver its own TTL plus an owner-reaffirm edge.Does anything other than wall-clock expiry drive
satisfied -> evidence_staletoday, or can a retrain or a config change pull that edge itself?