## Summary - add the Evidence Snapshot domain with immutable tenant-scoped snapshots, per-dimension items, queued generation, audit actions, badge mappings, and Filament list/detail surfaces - add the workspace evidence overview, capability and policy wiring, Livewire update-path hardening, and review-pack integration through explicit evidence snapshot resolution - add spec 153 artifacts, migrations, factories, and focused Pest coverage for evidence, review-pack reuse, authorization, action-surface regressions, and audit behavior ## Testing - `vendor/bin/sail artisan test --compact --stop-on-failure` - `CI=1 vendor/bin/sail artisan test --compact` - `vendor/bin/sail bin pint --dirty --format agent` ## Notes - branch: `153-evidence-domain-foundation` - commit: `b7dfa279` - spec: `specs/153-evidence-domain-foundation/` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #183
3.7 KiB
3.7 KiB
Data Model: Evidence Domain Foundation
1. EvidenceSnapshot
- Purpose: Immutable, tenant-scoped evidence package captured at a specific point in time and reused by downstream consumers.
- Ownership: Tenant-owned (
workspace_id+tenant_idNOT NULL) - Fields:
idworkspace_idtenant_idoperation_run_idnullableinitiated_by_user_idnullablefingerprintnullable, 64-char SHA-256previous_fingerprintnullablestatusenum:queued,generating,active,superseded,expired,failedcompleteness_stateenum:complete,partial,missing,stalesummaryJSONBgenerated_attimestampTz nullableexpires_attimestampTz nullablecreated_at,updated_at
- Relationships:
- belongs to
Workspace - belongs to
Tenant - belongs to
OperationRun - belongs to initiator
User - has many
EvidenceSnapshotItem
- belongs to
- Validation / invariants:
workspace_idandtenant_idrequired on every row- successful snapshots are immutable in content after
statusbecomesactive - one active snapshot per tenant evidence scope in v1
- identical fingerprint for the same tenant scope reuses the existing non-expired snapshot
2. EvidenceSnapshotItem
- Purpose: One curated evidence dimension inside an evidence snapshot.
- Ownership: Tenant-owned (
workspace_id+tenant_idNOT NULL) - Fields:
idevidence_snapshot_idworkspace_idtenant_iddimension_keystringstateenum:complete,partial,missing,stalerequiredbooleansource_kindstringsource_record_typenullable stringsource_record_idnullable stringsource_fingerprintnullable stringmeasured_attimestampTz nullablefreshness_attimestampTz nullablesummary_payloadJSONBsort_orderinteger default 0created_at,updated_at
- Relationships:
- belongs to
EvidenceSnapshot
- belongs to
- Validation / invariants:
- unique per snapshot:
(evidence_snapshot_id, dimension_key) workspace_id/tenant_idmust match the parent snapshotsummary_payloadstores curated summary/reference data only; no secrets, tokens, or raw Graph dumps
- unique per snapshot:
3. Evidence dimensions in first rollout
findings_summarypermission_postureentra_admin_rolesbaseline_drift_postureoperations_summary
Each dimension stores:
- inclusion state (
complete|partial|missing|stale) - source provenance (record type, identifier, fingerprint)
- freshness timestamp
- dimension-specific summary payload
4. Derived completeness rules
- Snapshot overall completeness precedence:
missingif any required dimension is missingstaleif no required dimensions are missing and at least one required dimension is stalepartialif no required dimensions are missing or stale and at least one required dimension is partialcompleteonly when all required dimensions are complete
5. Lifecycle transitions
EvidenceSnapshot status
queued -> generatinggenerating -> activegenerating -> failedactive -> supersededactive -> expiredsuperseded -> expired
No transition may mutate snapshot items after active is reached.
6. Downstream resolution contract
EvidenceResolutionRequest
- Purpose: Explicit request from a downstream consumer for a tenant evidence package.
- Fields:
workspace_idtenant_idsnapshot_idnullable explicit selectionrequired_dimensionsarrayallow_staleboolean defaultfalse
EvidenceResolutionResult
- Outcomes:
resolvedwith snapshot id and eligible dimensionsmissing_snapshotsnapshot_ineligiblewith missing/stale dimension reasons