## 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
12 KiB
Feature Specification: Unified Badge System (Single Source of Truth) v1
Feature Branch: 059-unified-badges
Created: 2026-01-22
Status: Draft
Input: Suite-wide badge/chip standardization so the same underlying value always renders with the same meaning (label + color + optional icon) across tables, dashboards/KPIs, and detail views; tenant-safe and DB-only at render time where required.
Clarifications
Session 2026-01-22
- Q: What is the v1 migration coverage target? → A: Status-like badges suite-wide; tag/category chips later.
- Q: What counts as “status-like” for v1 scope? → A: Status/health plus severity/risk signals.
- Q: Should v1 introduce any new severity levels (e.g., “critical”), or standardize the existing severity values only? → A: Standardize existing severity values only (no new levels in v1).
- Q: Should v1 include an automated “no ad-hoc badge semantics” guard beyond mapping tests? → A: Yes — tests plus a lightweight automated guard that flags ad-hoc mappings.
- Q: What is the canonical meaning for drift finding severity (low | medium | high) in v1? → A: low = neutral, medium = warning, high = danger.
User Scenarios & Testing (mandatory)
User Story 1 - Trustworthy status badges everywhere (Priority: P1)
As a tenant admin, I can trust that status/health and severity/risk badges mean the same thing everywhere in the admin panel, so I can scan lists quickly and make the right decision.
Why this priority: Inconsistent badge semantics create operational mistakes (false “success”, missed failures) and erode trust in the UI.
Independent Test: View a representative set of pages that contain status/health and severity/risk badges (lists + detail views) and confirm the same underlying value always uses the same label and visual meaning across pages.
Acceptance Scenarios:
- Given a run is in the “queued” state, When I view it in any table, dashboard list, or detail view, Then it is clearly shown as “Queued” with a consistent visual meaning that indicates “waiting to start”.
- Given a run is in the “running” state, When I view it in any table, dashboard list, or detail view, Then it is clearly shown as “Running” with a consistent visual meaning that indicates “in progress”.
- Given a run is in a successful terminal state (“succeeded” / “completed”), When I view it anywhere, Then it is shown with a consistent “success” meaning and is never shown using warning/attention colors.
- Given a finding has a high-severity value, When I view it in any table, dashboard list, or detail view, Then it is shown with a consistent “high severity” meaning and is never shown as a neutral or low-attention meaning.
User Story 2 - Readable status badges in dark mode (Priority: P2)
As a tenant admin, I can scan status badges in both light and dark mode without readability regressions.
Why this priority: Badges are a high-density UI element; readability and correct “good/bad” signaling reduce cognitive load and prevent mistakes.
Independent Test: Open key list pages and dashboards in dark mode and light mode and verify status badges remain readable without relying on fragile per-page styling overrides.
Acceptance Scenarios:
- Given I use dark mode, When I view status-like badges on common pages, Then badge text and any icons remain readable and do not rely on fragile per-page styling overrides.
- Given a status badge includes an icon in a dense list, When I view it, Then the icon appearance matches the badge meaning and does not appear disabled unless the status is intentionally neutral.
User Story 3 - Consistency stays enforced over time (Priority: P3)
As a maintainer, I can update badge semantics in one place and have the change apply everywhere, and regressions are caught before release.
Why this priority: Without enforcement, ad-hoc badge mappings quickly reappear and the UI drifts back into inconsistent meanings.
Independent Test: Make a small change to a centralized badge definition and confirm it affects multiple UI surfaces; introduce a deliberately inconsistent mapping and confirm automated validation fails.
Acceptance Scenarios:
- Given a new status value is introduced, When it is not yet defined in the central badge system, Then it displays with a safe “unknown” meaning rather than being misrepresented as success or warning.
- Given a developer attempts to reintroduce an ad-hoc badge mapping, When automated validation runs, Then it is detected and fails until the centralized definition is used.
[Add more user stories as needed, each with an assigned priority]
Edge Cases
- A record has an unrecognized/legacy status value (null/empty/unknown string).
- A record has an unrecognized/legacy severity/risk value.
- The same status appears on multiple pages (list + detail) and must remain consistent.
- A status value exists across multiple “domains” (e.g., “completed” used in different workflows) and must not be conflated if meanings differ.
- Dark mode and high-contrast settings reduce readability of badge text or icons.
- A page that must remain read-only/DB-only accidentally introduces side effects during render (for example, remote calls or background work).
- Tenant switching occurs mid-session and badges must not leak cross-tenant data.
Requirements (mandatory)
Constitution alignment (required): If this feature introduces any Microsoft Graph calls, any write/change behavior,
or any long-running/queued/scheduled work, the spec MUST describe contract registry updates, safety gates
(preview/confirmation/audit), tenant isolation, run observability (OperationRun type/identity/visibility), and tests.
If security-relevant DB-only actions intentionally skip OperationRun, the spec MUST describe AuditLog entries.
Functional Requirements
- FR-001: The system MUST define badge semantics centrally for each status badge “domain” used in the admin UI, including: label, color meaning, and (when applicable) an icon.
- FR-002: The system MUST apply the centralized status badge semantics consistently across all status badge surfaces (tables, dashboards/KPIs, and detail views) so the same underlying value always renders with the same meaning.
- FR-003: The system MUST clearly distinguish “status-like” badges (status/health and severity/risk signals) from tag/category chips so scope boundaries are unambiguous; v1 MUST standardize status-like badges suite-wide.
- FR-004: The system MUST standardize the canonical meanings for run-like statuses at minimum: queued, running, succeeded/completed, partial, failed.
- FR-005: Warning/attention colors (e.g., orange/yellow) MUST be reserved for “queued / needs attention / partial / in progress” meanings and MUST NOT represent success/completed outcomes.
- FR-006: Badge rendering MUST remain tenant-safe: it must not display cross-tenant data and must rely only on data already available in the current tenant context.
- FR-007: For designated DB-only pages (for example, Monitoring/Operations views), badge rendering MUST NOT trigger outbound network requests, background jobs, or other side effects during render or during automatic refresh/polling.
- FR-008: Badge rendering MUST be performant and predictable: it must not require additional data lookups at view time and must not introduce noticeable delays on high-row-count tables.
- FR-009: In dense tables, badges MAY include icons for scanability; when icons are shown, they MUST not appear disabled/gray unless the badge itself is intentionally neutral.
- FR-010: The system MUST provide a safe default for unrecognized values (neutral + clearly labeled as unknown) to avoid misleading operators.
- FR-011: The admin UI MUST be migrated so existing status-like badges/chips use the centralized system across the suite; tag/category chips are explicitly out of scope for v1 migration and may remain unchanged.
- FR-012: The delivery MUST include automated regression checks that validate canonical mappings (including “success is never warning”) and prevent reintroducing ad-hoc badge semantics.
- FR-013: This change MUST be limited to badge/chip rendering semantics; it MUST NOT change underlying workflow logic, status definitions, or page layouts beyond what is required to standardize badge rendering.
- FR-014: Severity/risk badges (for example, findings severity) MUST be standardized and rendered consistently across all in-scope pages.
- FR-015: The system MUST NOT introduce new severity levels as part of this feature; it MUST standardize and render existing severity values consistently.
- FR-016: The delivery MUST include a lightweight automated guard that detects newly introduced ad-hoc status/health or severity/risk badge semantics and blocks release until the centralized system is used.
- FR-017: Drift finding severity MUST have a canonical meaning: low = neutral, medium = warning, high = danger.
Assumptions & Dependencies
- Existing status values and business meanings are already established; this feature standardizes how they are presented, not what they mean.
- A defined set of status-like badge domains exists across the suite (runs, findings status, tenant status, availability, enabled/disabled, severity/risk); any newly discovered status-like domains will be included in the v1 standardization scope.
- Dark mode is supported and is considered in acceptance for badge readability.
- Tag/category chip standardization (policy type/platform/environment) is deferred to a later version.
- Severity level changes (such as adding “critical”) are deferred to a later version.
Key Entities (include if feature involves data)
- Badge Domain: A named category of values that share a consistent badge meaning (for example, “Operation run status”).
- Badge Definition: The centralized mapping for a domain’s values to label + color meaning + optional icon.
- Status Badge: A badge that communicates progress/outcome/health or severity/risk (for example, queued/running/succeeded).
- Tag Badge: A badge that communicates categorization/metadata (for example, platform/type/environment).
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: For each defined status badge domain, the same value renders with the same label and visual meaning across all in-scope pages in 100% of validation runs.
- SC-002: Across the in-scope admin UI, 0 instances exist where a success/completed outcome is presented using a warning/attention badge meaning.
- SC-003: Viewing designated DB-only pages triggers 0 outbound network requests and 0 background work as a side effect of badge rendering, in 100% of regression runs.
- SC-004: Status-badge-related UI regressions (incorrect label/color/icon meaning) decrease by at least 80% in the 30 days after release compared to the previous 30 days.