Automatisch erstellt: Commit & Push aus Workspace (WIP) Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #298
4.9 KiB
Data Model — Enforce Creation-Time Finding Invariants
Spec: spec.md
This feature introduces no new persisted truth. The data-model impact is to make the existing Finding lifecycle contract explicit at create, refresh, and reopen time across the three active writer families.
Existing Canonical Entities Reused
Finding (findings)
Purpose: Tenant-owned findings workflow truth.
Key fields already in use:
idworkspace_idtenant_idfinding_typesourcescope_keyfingerprintrecurrence_keyseveritystatusfirst_seen_atlast_seen_attimes_seensla_daysdue_atreopened_atresolved_atresolved_reasonclosed_atclosed_reasoncurrent_operation_run_idbaseline_operation_run_id
Feature use:
- Remains the single persisted source of truth for active findings lifecycle state.
- Continues to require both
workspace_idandtenant_idanchors. - Keeps the current status families unchanged.
- Carries the lifecycle-ready fields that this feature hardens at write time.
OperationRun (operation_runs)
Purpose: Existing execution context for baseline compare and other operational flows.
Feature use:
- Remains contextual only.
current_operation_run_idcontinues to identify the current writer run where the family already sets it.- No new operation type or new run-tracking artifact is introduced.
StoredReport (stored_reports)
Purpose: Existing stored reporting artifact for permission posture output.
Feature use:
- Unchanged.
- Mentioned only because permission posture finding generation already correlates lifecycle-ready findings with an existing report artifact.
Derived Non-Persisted Contracts
LifecycleReadyFinding (derived contract)
Definition: A Finding record that is immediately usable by the existing workflow the moment the active writer persists or refreshes it.
Required fields:
- active canonical status on first create (
new) first_seen_atlast_seen_attimes_seen >= 1sla_dayswhen the current severity policy returns a valuedue_atwhen the current severity policy requires due-date truth- existing run correlation fields preserved where the writer already populates them
Removal rule:
- no later repair surface may be required for these fields on active writers
RecurrenceIdentity (derived contract)
Definition: The family-owned identity that decides whether a repeated observation refreshes one canonical finding or incorrectly creates a duplicate.
Family-specific variants:
- baseline compare:
recurrence_keyandfingerprintderived from tenant, baseline profile, policy type, subject key, and change type - Entra admin roles: existing role-assignment and aggregate fingerprints
- permission posture: existing permission and error fingerprints
Guarantee:
- repeated observation of the same canonical issue reuses one finding identity
ObservationBoundary (derived contract)
Definition: The family-specific rule that decides whether times_seen should advance.
Family-specific variants:
- baseline compare: same
current_operation_run_idmust not incrementtimes_seentwice for the same observation - Entra admin roles: later
observedAtadvances seen history - permission posture: later
observedAtadvances seen history
Guarantee:
- retries and repeated processing do not double count the same observation
State Transitions Reused
Create
- missing canonical finding identity -> create one
Finding - resulting state remains
new - lifecycle-ready fields are populated in the same write path
Refresh Existing Open Finding
- existing open finding remains in its current active workflow state
- evidence or severity may refresh according to the writer family
- missing lifecycle-ready fields covered by this feature are repaired inline
- valid existing lifecycle fields should not be needlessly reset
Reopen Existing Terminal Finding
- existing terminal finding transitions through
FindingWorkflowService::reopenBySystem() - resulting state becomes
reopened resolved_*andclosed_*markers clear according to the current service behavior- SLA and due-state truth are recalculated from the later re-observation moment
Invariant Rules
- No new persisted entity, table, or compatibility artifact may be introduced.
- No new workflow status, reopen reason family, or lifecycle label may be introduced.
- Active writers must repair incomplete lifecycle-ready fields inline rather than relying on CLI repair commands, tenant maintenance actions, or deploy-time hooks.
- Due-state repair should fill missing truth or refresh terminal-to-reopened truth only; it must not silently redesign current due-date semantics for already-healthy open findings.
- A later database constraint is a separate follow-up candidate only if application-level write-path enforcement proves insufficient.