## Summary - centralize all status-like badge semantics via `BadgeCatalog`/`BadgeRenderer` and new per-domain mappings plus coverage for every affected entity - replace ad-hoc badge colors in Filament tables/views with the shared catalog and add a guard test that blocks new inline semantics - stabilize restore views by avoiding `@php(...)` shorthand so Blade compiles cleanly, and document BADGE-001 in the constitution/templates ## Testing - `vendor/bin/sail php vendor/bin/pint --dirty` - `vendor/bin/sail artisan test tests/Unit/Badges tests/Feature/Guards/NoAdHocStatusBadgesTest.php` - `vendor/bin/sail artisan test tests/Feature/Monitoring/OperationsDbOnlyTest.php tests/Feature/Monitoring/OperationsTenantScopeTest.php` - `vendor/bin/sail artisan test tests/Feature/RestoreRunWizardMetadataTest.php tests/Feature/Filament/SettingsCatalogRestoreApplySettingsPatchTest.php` Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local> Reviewed-on: #71
63 lines
4.3 KiB
Markdown
63 lines
4.3 KiB
Markdown
# Research — Unified Badge System (Single Source of Truth) v1
|
|
|
|
## Goal
|
|
Standardize status/health and severity/risk badge semantics suite-wide so operators can reliably scan the admin UI without misread signals (for example, “success” never appearing as warning).
|
|
|
|
V1 scope explicitly excludes tag/category chips (policy type/platform/environment).
|
|
|
|
## Existing Code & Patterns (to reuse)
|
|
|
|
### Filament badge surfaces (current)
|
|
- Tables already use `TextColumn::badge()` in many places.
|
|
- Ad-hoc status and severity mapping exists in several hotspots, for example:
|
|
- `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Filament/Pages/Monitoring/Operations.php`
|
|
- `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Filament/Widgets/Dashboard/RecentDriftFindings.php`
|
|
- `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/resources/views/filament/forms/components/restore-run-checks.blade.php`
|
|
|
|
### Guard test pattern (current)
|
|
- The repo already uses Pest “guard” tests that scan the codebase for forbidden patterns:
|
|
- `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/Feature/Guards/NoLegacyBulkOperationsTest.php`
|
|
|
|
### Status / severity sources (current)
|
|
Status-like values already exist in models/enums and must remain the source of truth for meaning:
|
|
- Operation runs: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Models/OperationRun.php` (status) + outcome usage in UI.
|
|
- Inventory sync runs: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Models/InventorySyncRun.php` (status constants).
|
|
- Backup schedule runs: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Models/BackupScheduleRun.php` (status constants).
|
|
- Entra group sync runs: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Models/EntraGroupSyncRun.php` (status constants).
|
|
- Restore runs: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Support/RestoreRunStatus.php` (enum).
|
|
- Findings: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/Models/Finding.php` (severity + status constants).
|
|
|
|
## Key Decisions
|
|
|
|
### Decision: Centralize status-like badge semantics behind domain mappers
|
|
- **Decision**: Introduce a central badge semantics layer that maps a “domain” + “value” to a single badge meaning (label + color meaning + optional icon).
|
|
- **Rationale**: Eliminates drift from per-page match blocks and keeps UI semantics testable and reviewable.
|
|
- **Alternatives considered**:
|
|
- **Inline mappings per resource/widget**: rejected (drifts quickly; hard to enforce).
|
|
- **Config-only mappings**: rejected for v1 (harder to type-check; still needs a rendering abstraction).
|
|
- **DB-stored mappings**: rejected (adds runtime dependency and migration/tenant complexity for no user value).
|
|
|
|
### Decision: V1 scope is “status-like” only (status/health + severity/risk)
|
|
- **Decision**: V1 migrates status-like badges suite-wide; tag/category chips are deferred.
|
|
- **Rationale**: Status/health and severity/risk are the highest-risk trust killers when inconsistent; tags are valuable but less safety-critical and more domain-specific.
|
|
|
|
### Decision: Canonical drift severity meanings
|
|
- **Decision**: Drift finding severity mapping is canonical: low = neutral, medium = warning, high = danger.
|
|
- **Rationale**: Severity is a risk/attention signal; “low” should not appear as “success”.
|
|
|
|
### Decision: No severity taxonomy changes in v1
|
|
- **Decision**: Do not add/rename severity levels (for example, do not introduce “critical” in v1).
|
|
- **Rationale**: This feature standardizes rendering semantics; changing underlying severity taxonomy is a separate scope and needs domain review.
|
|
|
|
### Decision: Enforcement is tests + a lightweight guard
|
|
- **Decision**: Add:
|
|
- Mapping tests per domain (including invariants like “success is never warning”).
|
|
- A lightweight guard test that flags newly introduced ad-hoc mappings for status/health and severity/risk.
|
|
- **Rationale**: Mapping tests prove correctness; the guard prevents regressions and enforces the single-source-of-truth rule.
|
|
- **Alternatives considered**:
|
|
- **Strict guard banning any badge usage not from the central system**: rejected (too brittle; would block deferred tag/category chip work and legitimate non-status uses).
|
|
|
|
## Open Questions
|
|
None — remaining work is implementation-time discovery of all status-like badge surfaces to migrate.
|
|
|