Granular Consent
Every trackable capability is backed by an explicit UserConsent record. This diagram follows its status field — undefined, unknown, accepted, revoked, suspended — as it is driven by the ConsentRequestDialogue, the fragment's validity window, and the Consent Overview page.
State diagram
stateDiagram-v2
[*] --> Undefined
Undefined --> Unknown : consent fragment loaded at startup
Unknown --> Prompted : gated action triggered (join / chat / share)
Prompted --> Accepted : user consents ("I consent")
Prompted --> Declined : user rejects (non-required item)
Declined --> Unknown
Accepted --> Suspended : "thinking it over" (data unused, record kept)
Suspended --> Accepted : re-agree
Suspended --> Revoked : confirm revoke
Accepted --> Revoked : revoke from Consent Overview
Revoked --> Prompted : capability re-triggered later
Accepted --> Expired : validFor window elapses
Expired --> Prompted : re-confirmation required
Revoked --> [*]
States
| State | Meaning |
|---|---|
| Undefined | No opinion recorded yet; default before any fragment loads. |
| Unknown | Fragment exists, but this user hasn't been asked. |
| Prompted | ConsentRequestDialogue is open, pre-selected, awaiting the user's decision. |
| Accepted | Active consent; capability is enabled while valid. |
| Declined | User rejected a non-required item at prompt time. |
| Suspended | Record kept, but data usage paused — a deliberate middle state. |
| Revoked | Explicitly withdrawn; capability disabled until re-prompted. |
| Expired | validFor minutes elapsed since last agreement. |
Reading the diagram
isExplicit(0/1/2) is orthogonal to this diagram — it records how a transition intoAcceptedhappened, not which state the consent is in.Suspendedis deliberately distinct fromRevoked: the record and its history survive, but the data stops being used until resolved.- Required consents that hit
Declinedblock the parent action (join, chat, etc.); optional ones simply skip the associated capability.