TenantAtlas/specs/046-inventory-sync-button/research.md
ahmido cf5b0027e3 046-inventory-sync-button (#47)
Zusammenfassung: Fügt im „Run Inventory Sync“-Modal einen include_dependencies-Toggle hinzu und persistiert die Auswahl in der InventorySyncRun.selection_payload. Tests, Quickstart und Tasks wurden entsprechend aktualisiert.

Files: InventoryLanding.php, InventorySyncButtonTest.php, quickstart.md, tasks.md
Motivation: Ermöglicht explizites Ein-/Ausschalten der Dependency-Extraktion pro Sync-Run (z. B. Assignments/Scope Tags/Foundations), statt starrer Defaults. Passt zur bestehenden selection_hash-Logik (InventorySelectionHasher) und zur deterministischen Selektionspersistenz.
Verhalten: include_dependencies ist im Modal standardmäßig true. Wird die Option gesetzt, landet der Wert als bool im selection_payload und beeinflusst selection_hash über die Normalisierung.
Tests: Neuer/angepasster Pest-Test stellt sicher, dass include_dependencies in selection_payload persistiert. Lokaler Testlauf:
./vendor/bin/sail artisan test tests/Feature/Inventory/InventorySyncButtonTest.php → alle Tests für diese Datei bestanden.
./vendor/bin/pint --dirty wurde ausgeführt (Formatting ok).
How to test (quick):
Start Sail + Queue:
Im Admin → Inventory: „Run Inventory Sync“ öffnen, Include dependencies umschalten, ausführen.
Prüfen: neu erstellter InventorySyncRun.selection_payload.include_dependencies ist der gesetzten Auswahl entsprechend. Oder laufen lassen:
Notes / Next steps:
Diese Änderung bereitet den Weg, später die Dependency-Extraction (042-inventory-dependencies-graph) optional tiefer zu integrieren.
Working tree ist sauber; es gibt ein nicht eingebundenes Verzeichnis 0800-future-features (unrelated).

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local>
Reviewed-on: #47
2026-01-09 22:15:04 +00:00

64 lines
3.6 KiB
Markdown

# Phase 0 Research: Inventory Sync Button (046)
**Date**: 2026-01-09
## Findings
### Existing patterns to reuse
#### DB-backed notifications
- Filament DB notifications are already used in multiple places.
- Example: Policy Sync action calls `Filament\Notifications\Notification::make()->sendToDatabase(auth()->user())->send()`.
#### Bottom-right progress widget
- The bottom-right progress widget is implemented by `App\Livewire\BulkOperationProgress` and renders `resources/views/livewire/bulk-operation-progress.blade.php`.
- It polls `BulkOperationRun` filtered by `tenant_id = Tenant::current()->id` and `user_id = auth()->id()`.
- It is injected globally into Filament via a render hook in `App\Providers\Filament\AdminPanelProvider`.
#### Inventory Sync run records
- Inventory sync runs are already persisted in `inventory_sync_runs` with counts and status.
- Current `InventorySyncService::syncNow(...)` runs inline and uses locks/concurrency to create/update `InventorySyncRun`.
#### Authorization
- The app already uses tenant-role based authorization for sync operations (e.g. `User::canSyncTenant($tenant)` in `TenantResource`).
#### Inventory selection payload
- Inventory Sync requires a selection payload with shape: `{policy_types: list<string>, categories: list<string>, include_foundations: bool, include_dependencies: bool}`.
- There is no existing UI picker for inventory selection.
## Decisions
### Decision: Start Inventory Sync as a queued job
- **Chosen**: Dispatch an Inventory Sync job from the UI action.
- **Rationale**: Aligns with existing background operation UX and avoids blocking Livewire requests.
- **Alternatives considered**:
- Run inline (current `syncNow`) — rejected due to UX (slow request) and mismatch with existing “progress widget” expectations.
### Decision: Use DB notifications + progress widget UX consistent with Policy/Bulk operations
- **Chosen**: Create a `BulkOperationRun` (resource `inventory`, action `sync`) so the existing bottom-right widget shows progress; also send DB notifications at start and completion/failure.
- **Rationale**: Matches established UX language and avoids inventing new UI surfaces.
- **Alternatives considered**:
- Only show toast notifications — rejected; user explicitly requires DB notification panel + progress widget.
### Decision: Authorize via tenant role sync permission
- **Chosen**: Gate the UI action using `auth()->user()->canSyncTenant(Tenant::current())`.
- **Rationale**: Aligns with existing “sync” authorization patterns already used for tenant/policy operations.
- **Alternatives considered**:
- Introduce new permission strings/roles — rejected for MVP; adds RBAC surface area.
### Decision: Default selection = “full inventory”
- **Chosen**: Dispatch inventory sync with policy types set to `PolicyTypeResolver::supportedPolicyTypes()`, empty categories, and `include_foundations=true`, `include_dependencies=true`.
- **Rationale**: Simplest interpretation of “Run Inventory Sync” without inventing a new picker UX.
- **Alternatives considered**:
- Reuse backup policy picker UI — rejected; different domain (backup selection), more UX than requested.
### Decision: Attribute initiator on run record and audit trail
- **Chosen**: Store initiator identity on `InventorySyncRun` and also emit an audit record.
- **Rationale**: Improves traceability and aligns with constitution principle “Automation must be Idempotent & Observable”.
- **Alternatives considered**:
- Audit log only — rejected (you chose C).
## Open Questions (for Phase 1 design)
- None remaining for planning; implementation will add a dedicated queued job.