Platform
A finding with a history, not just a severity
The lifecycle is one state machine, implemented once. Its transition table is data, so an exhaustive test can enumerate every pair of states and assert the answer — including the transitions that must be refused, which is most of what a state machine is for.
The states
Five, and the moves between them
- open
- A scan observed it. Nobody has looked yet.
- triaged
- Someone has read it and accepted it into the backlog.
- suppressed
- Risk accepted, with a reason, an owner, and an expiry of at most two years.
- resolved
- A scan that would have found it did not. Only evidence closes a finding.
- reopened
- It was fixed and came back. Permanently distinguishable from never-fixed.
open → triaged, suppressed
triaged → open, suppressed
reopened → triaged, suppressed
suppressed→ open, triaged, suppressed (amend)
resolved → reopened
Everything else is refused.Three decisions
Rules that are opinions, not omissions
Each of these is a thing the product will not let you do, and the reason it will not.
A person cannot mark a finding resolved
“Resolved” means a scan that would have found it did not. That is a statement about evidence. A button that set it would let someone assert evidence they do not have, and the next scan would contradict them. Fix it and rescan, or suppress it with a reason.
A resolved finding cannot be suppressed
There is nothing to suppress — it is already closed. Pre-emptively accepting a risk that may return is a statement about a class of issue, which makes it a policy rule rather than a note on one row.
A reopened finding cannot be relabelled as open
“Reopened” records that something was fixed once and came back. That is the most interesting fact a vulnerability programme produces, and quietly downgrading it would erase a regression from the backlog while the timeline still says it happened.
Identity
Why the decision survives the rescan
A finding's identity is derived from its content — not from its position in a report, and not from anything that legitimately changes.
Severity, line numbers and the installed version are deliberately excluded from identity. A vulnerability that is re-rated is the same vulnerability; a package that moved is the same finding. If identity included those, every re-rating would orphan the triage you had already done and hand you a brand-new finding to decide about again.
Because identity is content-derived rather than engine-derived, it also survives a change of detection engine. That matters commercially: the decision record is TRUSTIVAN's, and it does not evaporate if what produces the raw findings is ever replaced.
Audit
Who did what, and what was merely automatic
Every transition writes to an append-only timeline that names the kind of actor responsible.
A change can be caused by a person, a scan, a scheduled system task, or an API key — and the record says which. No audit row ever claims a person did something a pipeline did.
The distinction extends to suppression. When an acceptance lapses, that is recorded as its own action, separate from someone actively changing their mind — because “the owner reconsidered” and “nobody renewed it” call for different conversations.
Audit coverage is complete for findings and verdicts, and extends to webhook, identity-provider, SCIM and membership changes. Asset changes are not yet recorded in the same way.