# 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.