# Implementation Plan: Unified Badge System (Single Source of Truth) v1 **Branch**: `059-unified-badges` | **Date**: 2026-01-22 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/059-unified-badges/spec.md` **Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/059-unified-badges/spec.md` **Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts. ## Summary - Standardize status/health and severity/risk badge semantics suite-wide using a centralized mapping system. - Migrate all status-like badge surfaces (tables, dashboards/KPIs, detail views) to use the central semantics. - Keep tag/category chips (policy type/platform/environment) out of scope for v1 (planned follow-up). - Add automated regression coverage: mapping tests + a lightweight guard that flags reintroduced ad-hoc mappings. ## Technical Context **Language/Version**: PHP 8.4.15 (Laravel 12) **Primary Dependencies**: Filament v5 + Livewire v4 **Storage**: PostgreSQL **Testing**: Pest v4 (PHPUnit v12 runtime via `php artisan test`) **Target Platform**: Web application (Filament admin panel) **Project Type**: Web (Laravel monolith) **Performance Goals**: Badge mapping is constant-time; no added queries or N+1; typical list pages render <2s for normal tenant sizes. **Constraints**: Tenant-scoped; status-like badge rendering must be DB-only and must not trigger outbound HTTP or job dispatch during render/polling/hydration. **Scale/Scope**: Suite-wide migration for status/health and severity/risk badges across tables, dashboards/KPIs, and detail views. ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Inventory-first: clarify what is “last observed” vs snapshots/backups - Read/write separation: any writes require preview + confirmation + audit + tests - Graph contract path: Graph calls only via `GraphClientInterface` + `config/graph_contracts.php` - Deterministic capabilities: capability derivation is testable (snapshot/golden tests) - Tenant isolation: all reads/writes tenant-scoped; cross-tenant views are explicit and access-checked - Run observability: long-running/remote/queued work creates/reuses `OperationRun`; start surfaces enqueue-only; Monitoring is DB-only; DB-only <2s actions may skip runs but security-relevant ones still audit-log - Automation: queued/scheduled ops use locks + idempotency; handle 429/503 with backoff+jitter - Data minimization: Inventory stores metadata + whitelisted meta; logs contain no secrets/tokens Status: ✅ No constitution violations (UI semantics only; no new Graph calls; no new write behavior; badge mapping is pure and tenant-safe). ## Project Structure ### Documentation (this feature) ```text /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/059-unified-badges/ ├── plan.md # This file (/speckit.plan command output) ├── research.md # Phase 0 output (/speckit.plan command) ├── data-model.md # Phase 1 output (/speckit.plan command) ├── quickstart.md # Phase 1 output (/speckit.plan command) ├── contracts/ # Phase 1 output (/speckit.plan command) └── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan) ``` ### Source Code (repository root) ```text /Users/ahmeddarrazi/Documents/projects/TenantAtlas/app/ ├── Filament/ │ ├── Pages/Monitoring/Operations.php # Update: migrate status/outcome badges to central mapping │ ├── Resources/ # Update: status-like columns/entries across resources │ └── Widgets/ # Update: status-like + severity badges in dashboard widgets ├── Support/ │ └── Badges/ # New: central badge semantics (status/health + severity/risk) └── Models/ # Existing: status/severity sources (OperationRun, Finding, etc.) /Users/ahmeddarrazi/Documents/projects/TenantAtlas/resources/views/ └── filament/ # Update: replace any ad-hoc status-like badge colors /Users/ahmeddarrazi/Documents/projects/TenantAtlas/tests/ ├── Feature/Guards/ # New: lightweight “no ad-hoc badge semantics” guard └── Unit/ # New/updated: badge mapping tests per domain ``` **Structure Decision**: Laravel monolith + Filament v5 conventions. Centralize semantics in `app/Support/Badges` and consume from Filament resources/pages/widgets + Blade views. ## Complexity Tracking > **Fill ONLY if Constitution Check has violations that must be justified** None. ## Phase 0 — Outline & Research (complete) - Output: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/059-unified-badges/research.md` - Key decisions captured: - v1 scope: status/health + severity/risk badges suite-wide; tag/category chips deferred. - Drift severity mapping: low = neutral, medium = warning, high = danger. - Enforcement: mapping tests + lightweight guard to prevent reintroducing ad-hoc mappings. ## Phase 1 — Design & Contracts (complete) ### Data model - Output: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/059-unified-badges/data-model.md` - No schema changes required; badge semantics derive from existing fields (status/outcome/severity booleans). ### Contracts - Output: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/059-unified-badges/contracts/badge-semantics.md` - Output: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/059-unified-badges/contracts/guardrails.md` ### Quickstart - Output: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/059-unified-badges/quickstart.md` ### Provider registration (Laravel 11+) - Panel providers remain registered in `bootstrap/providers.php` (no changes required for this feature unless adding a new provider). ### Livewire / Filament version safety - Livewire v4.0+ (required by Filament v5) is in use. ### Asset strategy - No new assets expected. If new panel assets are introduced during implementation, ensure deployment runs `php artisan filament:assets`. ### Destructive actions - None introduced in this feature. ### Constitution re-check (post-design) - ✅ Inventory-first / Snapshots-second: unaffected (UI-only semantics). - ✅ Read/write separation: this feature is read-only. - ✅ Graph contract path: no Graph calls added. - ✅ Tenant isolation: badge mapping is pure and uses already-available tenant-scoped data. - ✅ Run observability: only consumes existing run records; does not introduce new long-running work. - ✅ Data minimization: no new payload storage. **Gate status (post-design)**: PASS ## Phase 2 — Implementation Plan (next) ### Story 1 (P1): Trustworthy status/health badges everywhere - Introduce a central badge semantics layer for status/health domains (runs, findings status, tenant status, booleans, availability). - Migrate all status-like badge surfaces suite-wide to the centralized mapping, prioritizing: - Monitoring/Operations list surfaces - Inventory sync runs and backup schedule runs - Restore runs - Findings status - Ensure the invariant: success/completed is never presented as warning/attention. ### Story 2 (P2): Readable status badges in dark mode - Remove fragile per-page color overrides for status-like badges in Blade where present. - Ensure status-like badges remain readable in dark mode and icons do not appear disabled unless intentionally neutral. ### Story 3 (P3): Consistency stays enforced over time - Add mapping tests per domain (including drift severity mapping and “success is never warning” invariants). - Add a lightweight guard test to detect newly introduced ad-hoc status/health or severity/risk badge mappings.