## 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
152 lines
12 KiB
Markdown
152 lines
12 KiB
Markdown
# 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)*
|
||
|
||
<!--
|
||
IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance.
|
||
Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them,
|
||
you should still have a viable MVP (Minimum Viable Product) that delivers value.
|
||
|
||
Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical.
|
||
Think of each story as a standalone slice of functionality that can be:
|
||
- Developed independently
|
||
- Tested independently
|
||
- Deployed independently
|
||
- Demonstrated to users independently
|
||
-->
|
||
|
||
### 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**:
|
||
|
||
1. **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”.
|
||
2. **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”.
|
||
3. **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.
|
||
4. **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**:
|
||
|
||
1. **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.
|
||
2. **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**:
|
||
|
||
1. **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.
|
||
2. **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.
|
||
|
||
<!--
|
||
ACTION REQUIRED: The content in this section represents placeholders.
|
||
Fill them out with the right functional requirements.
|
||
-->
|
||
|
||
### 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)*
|
||
|
||
<!--
|
||
ACTION REQUIRED: Define measurable success criteria.
|
||
These must be technology-agnostic and measurable.
|
||
-->
|
||
|
||
### 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.
|