5.5 KiB
5.5 KiB
Data Model: Finding Risk Acceptance Lifecycle
1. FindingException
- Purpose: Tenant-owned governance aggregate that represents the current accepted-risk exception state for one finding.
- Ownership: Tenant-owned (
workspace_id+tenant_idNOT NULL). - Fields:
idworkspace_idtenant_idfinding_idstatusenum:pending,active,expiring,expired,rejected,revoked,supersededrequested_by_user_idowner_user_idapproved_by_user_idnullablecurrent_decision_idnullablerequest_reasontextapproval_reasontext nullablerejection_reasontext nullablerevocation_reasontext nullablerequested_atapproved_atnullablerejected_atnullablerevoked_atnullableeffective_fromnullableexpires_atnullablereview_due_atnullableevidence_summaryJSONB nullablecurrent_validity_stateenum:valid,expiring,expired,revoked,rejected,missing_supportcreated_at,updated_at
- Relationships:
- belongs to
Finding - belongs to
Tenant - belongs to
Workspace - belongs to requester
User - belongs to owner
User - belongs to approver
User - has many
FindingExceptionDecision - has many
FindingExceptionEvidenceReference
- belongs to
- Validation / invariants:
workspace_id,tenant_id, andfinding_idare always required.finding_idmust reference a finding in the same workspace and tenant.- At most one current valid active exception may govern one finding at a time.
approved_by_user_idmust differ fromrequested_by_user_idin v1.expires_atmust be aftereffective_fromwhen both are present.
2. FindingExceptionDecision
- Purpose: Append-only historical record of every exception lifecycle decision.
- Ownership: Tenant-owned (
workspace_id+tenant_idNOT NULL). - Fields:
idworkspace_idtenant_idfinding_exception_iddecision_typeenum:requested,approved,rejected,renewal_requested,renewed,revokedactor_user_idreasontext nullableeffective_fromnullableexpires_atnullablemetadataJSONB nullabledecided_atcreated_at,updated_at
- Relationships:
- belongs to
FindingException - belongs to actor
User
- belongs to
- Validation / invariants:
- Decision rows are append-only after creation.
- Decision type must be compatible with the parent exception's lifecycle state.
- Renewal decisions must not erase prior approval or rejection records.
3. FindingExceptionEvidenceReference
- Purpose: Structured pointer to evidence used to justify or review the exception.
- Ownership: Tenant-owned (
workspace_id+tenant_idNOT NULL). - Fields:
idworkspace_idtenant_idfinding_exception_idsource_typestringsource_idstring nullablesource_fingerprintstring nullablelabelstringsummary_payloadJSONB nullablemeasured_atnullablecreated_at,updated_at
- Relationships:
- belongs to
FindingException
- belongs to
- Validation / invariants:
- References must stay intelligible even if the live source artifact later expires or is removed from active views.
summary_payloadis bounded, sanitized, and not a raw payload dump.
4. Finding Risk Governance Projection
- Purpose: Derived truth used by finding detail, tenant exception lists, canonical queues, and downstream evidence/reporting consumers.
- Derived from:
Finding.statusFindingException.status- exception validity window (
effective_from,expires_at) - current exception evidence support state
- Values:
ungovernedpending_exceptionvalid_exceptionexpiring_exceptionexpired_exceptionrevoked_exceptionrejected_exceptionrisk_accepted_without_valid_exception
- Invariant:
- Downstream consumers must use this projection, not finding status alone, when determining whether accepted risk is currently governed.
State Transitions
FindingException
pending->activeon approvalpending->rejectedon rejectionactive->expiringwhen within reminder thresholdactive|expiring->expiredwhenexpires_atpassesactive|expiring->revokedon explicit revokeactive|expiring|expired->supersededwhen a renewal produces a newer governing decision under the same aggregate semantics
FindingExceptionDecision
requestedalways occurs firstapprovedorrejectedresolves a pending requestrenewal_requestedmay occur fromactive,expiring, orexpiredrenewedextends a current or lapsed exception through a new decisionrevokedends current validity explicitly
Indexing and Query Needs
- Composite indexes on
(workspace_id, tenant_id, status)for tenant register filtering. - Composite indexes on
(workspace_id, status, review_due_at)for canonical queue and expiring views. - Unique partial index to prevent more than one current valid active exception per finding.
- Composite index on
(finding_id, tenant_id)for finding-detail resolution.
Relationship to Existing Domain Records
Findingremains the system of record for the detected issue and status workflow.FindingWorkflowServiceremains the only allowed path for changing finding status.AuditLogremains the immutable historical event stream for every lifecycle mutation.EvidenceSnapshotand related artifacts remain separate systems of record referenced by exception evidence links.