3.6 KiB
3.6 KiB
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\BulkOperationProgressand rendersresources/views/livewire/bulk-operation-progress.blade.php. - It polls
BulkOperationRunfiltered bytenant_id = Tenant::current()->idanduser_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_runswith counts and status. - Current
InventorySyncService::syncNow(...)runs inline and uses locks/concurrency to create/updateInventorySyncRun.
Authorization
- The app already uses tenant-role based authorization for sync operations (e.g.
User::canSyncTenant($tenant)inTenantResource).
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.
- Run inline (current
Decision: Use DB notifications + progress widget UX consistent with Policy/Bulk operations
- Chosen: Create a
BulkOperationRun(resourceinventory, actionsync) 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, andinclude_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
InventorySyncRunand also emit an audit record. - Rationale: Improves traceability and aligns with constitution principle “Operations / Run Observability Standard”.
- 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.