feat/042-inventory-dependencies-graph (#50)
Dieses PR liefert den Inventory Dependencies Graph end-to-end: Abhängigkeiten (Edges) werden aus Inventory-Sync-Daten extrahiert, tenant-sicher gespeichert und in der Inventory Item Detailansicht angezeigt.
Ziel: Admins können Prerequisites + Blast Radius (direct) schnell erkennen, ohne Snapshot/Restore anzufassen.
⸻
Was ist drin?
Dependency Graph (Edges)
• inventory_links Schema + Indizes + idempotentes Upsert (Unique Key)
• Relationship Types (u.a.):
• assigned_to_include, assigned_to_exclude
• uses_assignment_filter
• scoped_by_scope_tag
• UI: Inventory Item → Dependencies Section
• Direction Filter: All / Inbound / Outbound
• Relationship Filter: All + spezifische Relationship Types
• Missing-Badge + sicheres Tooltip (safe subset)
Safety / Observability
• Unknown/unsupported Shapes erzeugen keine Edges, sondern:
• Warning in InventorySyncRun.error_context.warnings[]
• optional info-log (ohne Secrets)
• Limit-only Semantik (MVP): bis zu 50 Edges pro Richtung (max 100 bei “All”)
• Blast Radius in MVP = direct only (kein depth>1 traversal)
Name Resolution (lokal, ohne Entra Calls)
• Resolver/DTO Layer für deterministische Labels (kein “Unknown” mehr)
• Auflösung aus lokaler DB nur für Foundations, wenn vorhanden:
• scope_tag → roleScopeTag
• assignment_filter → assignmentFilter
• aad_group bleibt bewusst external ref: “Group (external): …” (keine Graph/Entra Lookups im UI)
• Zentraler FoundationTypeMap als Source-of-Truth (keine Hardcodings)
⸻
Out of Scope / Follow-up
• Entra Group Name Resolution (braucht eigenes “Group Inventory” Modul + Permissions)
• Foundations als Inventory Items / Coverage Tab (Scope Tags / Assignment Filters sichtbar & syncbar)
→ folgt als separater PR (Inventory Core/UI), damit 042 sauber “Edges-only” bleibt.
⸻
Tests / Verifikation
• Targeted Pest Tests (Unit + Feature + UI smoke) für:
• deterministische Edge-Erzeugung + idempotent upsert
• tenant isolation (UI/Query)
• warnings auf Run Record
• resolver/name rendering + links (wo möglich)
• pint --dirty ausgeführt
⸻
Manual QA (UI)
1. Inventory Sync Run mit include_dependencies=true starten
2. Inventory Item öffnen → Dependencies prüfen:
• include/exclude + filter + scoped_by sichtbar (wenn vorhanden)
• Relationship/Direction Filter funktionieren
• keine “Unknown” Labels mehr, sondern deterministische Labels
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local>
Reviewed-on: #50