diff --git a/.github/agents/copilot-instructions.md b/.github/agents/copilot-instructions.md index 310d6a9..f1ecfec 100644 --- a/.github/agents/copilot-instructions.md +++ b/.github/agents/copilot-instructions.md @@ -11,6 +11,7 @@ ## Active Technologies - PHP 8.4.x (Laravel 12) + Laravel 12, Filament v4, Livewire v3 (feat/047-inventory-foundations-nodes) - PostgreSQL (JSONB for `InventoryItem.meta_jsonb`) (feat/047-inventory-foundations-nodes) - PostgreSQL (JSONB in `operation_runs.context`, `operation_runs.summary_counts`) (056-remove-legacy-bulkops) +- PHP 8.4.15 (Laravel 12.47.0) + Filament v5.0.0, Livewire v4.0.1 (058-tenant-ui-polish) - PHP 8.4.15 (feat/005-bulk-operations) @@ -30,9 +31,9 @@ ## Code Style PHP 8.4.15: Follow standard conventions ## Recent Changes +- 058-tenant-ui-polish: Added PHP 8.4.15 (Laravel 12.47.0) + Filament v5.0.0, Livewire v4.0.1 +- 058-tenant-ui-polish: Added [if applicable, e.g., PostgreSQL, CoreData, files or N/A] - 056-remove-legacy-bulkops: Added PHP 8.4.x + Laravel 12, Filament v4, Livewire v3 -- feat/047-inventory-foundations-nodes: Added PHP 8.4.x (Laravel 12) + Laravel 12, Filament v4, Livewire v3 -- feat/042-inventory-dependencies-graph: Added PHP 8.4.x + Laravel 12, Filament v4, Livewire v3 diff --git a/specs/057-filament-v5-upgrade/checklists/requirements.md b/specs/057-filament-v5-upgrade/checklists/requirements.md index 3ceac5d..7cb996b 100644 --- a/specs/057-filament-v5-upgrade/checklists/requirements.md +++ b/specs/057-filament-v5-upgrade/checklists/requirements.md @@ -31,5 +31,5 @@ ## Feature Readiness ## Notes -- This is a technical upgrade, but the spec intentionally describes outcomes and guardrails rather than implementation steps. -- Proceed to planning: identify concrete packages, versions, and migration steps in plan/tasks. +- This is a technical upgrade, but the spec describes outcomes and guardrails rather than implementation steps. +- Planning can capture concrete versions, dependency changes, and migration steps. diff --git a/specs/057-filament-v5-upgrade/spec.md b/specs/057-filament-v5-upgrade/spec.md index 06208b0..4bc3e16 100644 --- a/specs/057-filament-v5-upgrade/spec.md +++ b/specs/057-filament-v5-upgrade/spec.md @@ -3,7 +3,7 @@ # Feature Specification: Admin UI Stack Upgrade (Panel + Suite) **Feature Branch**: `057-filament-v5-upgrade` **Created**: 2026-01-20 **Status**: Draft -**Input**: Upgrade the existing admin UI stack to the next supported major release to maintain compatibility and support, and ensure no regressions for tenant isolation and Ops-UX/Monitoring guardrails. +**Input**: Upgrade the existing admin UI stack to the next supported major release to maintain compatibility and support, and ensure no regressions for tenant isolation and Monitoring/Operations safety guardrails. ## Clarifications @@ -19,7 +19,7 @@ ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Admin UI keeps working after upgrade (Priority: P1) -Administrators can sign in and use the admin panel (navigation, resources, forms, tables, actions) without runtime errors after the upgrade. +Administrators can sign in and use the admin panel (navigation, lists, forms, actions) without runtime errors after the upgrade. **Why this priority**: This is the minimum bar for the upgrade to be safe; if the admin UI is unstable, all operational work stops. @@ -75,18 +75,18 @@ ## Requirements *(mandatory)* ### Functional Requirements -- **FR-001**: The application MUST upgrade the admin panel stack to the next supported major release and its required compatible reactive UI layer. -- **FR-002**: The application MUST continue to support the existing styling system without asset build failures. -- **FR-003**: All existing Filament panels MUST load successfully for authorized users and preserve core interactions (navigation, tables, forms, actions, notifications, widgets). -- **FR-004**: SPA-style navigation flows MUST continue to work, including global widget mounting and event delivery across navigation. -- **FR-005**: Everything rendered under the Monitoring → Operations navigation section (including widgets/partials/tabs) MUST remain DB-only: no outbound HTTP requests are permitted during page render or during background/automatic Livewire requests (polling/auto-refresh/hydration). -- **FR-010**: Any remote work initiated from Monitoring/Operations pages MUST be triggered only by explicit user actions (e.g., buttons) and MUST enqueue tracked operations (e.g., `OperationRun`-backed jobs) rather than performing outbound HTTP inline. -- **FR-006**: Tenant isolation MUST be preserved across requests and Live UI interactions: all reads/writes/events/caches MUST scope to the active tenant. -- **FR-007**: Compatibility risks MUST be managed by producing an explicit inventory of affected third-party packages and documenting upgrade/replacement decisions. -- **FR-011**: If a third-party package is incompatible with the upgraded stack, the system MUST preserve equivalent functionality by upgrading or replacing the package; mixed-version pinning is not allowed. Any unavoidable feature loss MUST be handled as an explicit scope/decision change. -- **FR-012**: Database migrations are allowed only if strictly required for compatibility; they MUST be reversible and non-destructive (no data loss). Migrations MUST include a safe `down()` path and avoid drops without an explicit plan, and MUST be mentioned in release notes. +- **FR-001**: The system MUST upgrade the admin UI stack to the next supported major release and remain fully functional for all in-scope admin workflows. +- **FR-002**: The system MUST continue to support the existing styling and asset pipeline without build failures. +- **FR-003**: All existing admin pages MUST load successfully for authorized users and preserve core interactions (navigation, lists, forms, actions, notifications, and global UI elements). +- **FR-004**: In-app navigation between admin pages MUST continue to work reliably, including any global progress indicators and event-driven UI behavior. +- **FR-005**: Everything rendered under the Monitoring → Operations navigation section (including widgets/partials/tabs) MUST remain DB-only: no outbound HTTP requests are permitted during page render or during background/automatic requests (polling/auto-refresh/hydration). +- **FR-006**: Tenant isolation MUST be preserved across requests and interactive UI behavior: all reads/writes/events/caches MUST scope to the active tenant. +- **FR-007**: Compatibility risks MUST be managed by producing an explicit inventory of affected third-party dependencies and documenting upgrade/replacement decisions. - **FR-008**: The upgrade MUST not introduce new Microsoft Graph read/write behavior; if any Graph-touching behavior changes are required, they MUST be explicitly specified with safety gates and observability updates. - **FR-009**: The upgrade MUST include a documented rollback procedure that restores the previous working state. +- **FR-010**: Any remote work initiated from Monitoring/Operations pages MUST be triggered only by explicit user actions and MUST enqueue a tracked operation (with an observable run record) rather than performing outbound HTTP inline. +- **FR-011**: If a third-party dependency is incompatible with the upgraded stack, the system MUST preserve equivalent functionality by upgrading or replacing the dependency; mixed-version pinning is not allowed. Any unavoidable feature loss MUST be handled as an explicit scope/decision change. +- **FR-012**: Database migrations are allowed only if strictly required for compatibility; they MUST be reversible and non-destructive (no data loss) and MUST be mentioned in release notes. ### Assumptions & Dependencies @@ -97,7 +97,7 @@ ### Assumptions & Dependencies ### Key Entities *(include if feature involves data)* - **Tenant**: The active tenant context that scopes all data access and UI state. -- **OperationRun**: The persisted record of long-running operations shown in Monitoring/Operations views. +- **Run Record**: The persisted record of long-running operations shown in Monitoring/Operations views. - **AuditLog**: The tenant-scoped audit trail used to retain accountability for sensitive actions. ## Success Criteria *(mandatory)* diff --git a/specs/058-tenant-ui-polish/contracts/polling.md b/specs/058-tenant-ui-polish/contracts/polling.md new file mode 100644 index 0000000..30ee404 --- /dev/null +++ b/specs/058-tenant-ui-polish/contracts/polling.md @@ -0,0 +1,22 @@ +# Polling Contract — Calm UI Rules + +## Principle +Polling is allowed only when it materially improves UX (active operations). It must be DB-only and must stop when no longer needed. + +## Dashboard +- Polling is enabled only while active runs exist (queued/running) for the current tenant. +- Polling is disabled when: + - No active runs exist. + +## Operations index +- Polling is enabled only while active runs exist. +- Polling is disabled when: + - No active runs exist. + +## Modals +- No polling inside modals. +- When a modal is open, polling should not cause churn in the background. + +## Technical approach +- Widgets: use `$pollingInterval = null` to disable polling. +- Tables: apply `$table->poll('10s')` only when active runs exist. diff --git a/specs/058-tenant-ui-polish/contracts/ui.md b/specs/058-tenant-ui-polish/contracts/ui.md new file mode 100644 index 0000000..b6b6256 --- /dev/null +++ b/specs/058-tenant-ui-polish/contracts/ui.md @@ -0,0 +1,28 @@ +# UI Contracts — Tenant UI Polish + +This feature does not introduce HTTP APIs. These contracts describe UI routing, filters, and definitions that must remain stable. + +## Routes (tenant-scoped) +- Dashboard: tenant dashboard page (new custom page; replaces default dashboard entry). +- Inventory hub: Inventory cluster root (routes to first page/resource in cluster). +- Inventory items: Inventory items resource index, under cluster prefix. +- Inventory sync runs: Inventory sync runs resource index, under cluster prefix. +- Inventory coverage: Inventory coverage page, under cluster prefix. +- Operations index: `OperationRunResource` index (`/operations`). +- Operation run detail: `OperationRunResource` view page. + +## Operations Tabs (FR-009) +Tabs filter the Operations table by: +- All: no extra constraints. +- Active: `status IN ('queued','running')` +- Succeeded: `status = 'completed' AND outcome = 'succeeded'` +- Partial: `status = 'completed' AND outcome = 'partial'` +- Failed: `status = 'completed' AND outcome = 'failed'` + +## KPI Definitions +- Inventory coverage % = Restorable / Total (Partial is separate, does not inflate %). +- Drift stale threshold = 7 days. +- “Recent” lists default size = 10. +- “Active operations” shows two counts: + - All active runs (queued + running) + - Inventory-active runs (type = `inventory.sync`, queued + running) diff --git a/specs/058-tenant-ui-polish/data-model.md b/specs/058-tenant-ui-polish/data-model.md new file mode 100644 index 0000000..d328232 --- /dev/null +++ b/specs/058-tenant-ui-polish/data-model.md @@ -0,0 +1,76 @@ +# Data Model — Tenant UI Polish + +This feature is read-only. It introduces no schema changes. + +## Entities + +### Tenant +- **Role**: scope boundary for all queries. +- **Source**: `Tenant::current()` (Filament tenancy). + +### OperationRun +- **Role**: operations feed, KPIs, and canonical “View run” destinations. +- **Key fields used** (existing): + - `tenant_id` + - `type` + - `status` (`queued|running|completed`) + - `outcome` (`succeeded|partial|failed|...`) + - `created_at`, `started_at`, `completed_at` + - `summary_counts`, `failure_summary` (JSONB) + +**Derived values**: +- **Active**: `status IN ('queued','running')` +- **Terminal**: `status = 'completed'` +- **Avg duration (7 days)**: only terminal runs with `started_at` and `completed_at`. + +### InventoryItem +- **Role**: inventory totals and coverage chips. +- **Key fields used** (existing, inferred from resources): + - `tenant_id` + - coverage-related flags / fields used to categorize: Restorable, Partial, Risk, Dependencies + +**Derived values**: +- Total items +- Coverage % = `restorable / total` (if total > 0) +- Chip counts: Restorable, Partial, Risk, Dependencies + +### InventorySyncRun +- **Role**: “Last Inventory Sync” and “Sync Runs” list. +- **Key fields used**: + - `tenant_id` + - status + timestamps + - any “selection_hash / selection payload” metadata used for display + +### Finding (Drift Finding) +- **Role**: drift KPIs and “Needs Attention”. +- **Key fields used** (existing migration): + - `tenant_id` + - `severity` (enum-like string) + - `status` (open/closed) + - timestamps + - `scope_key` for grouping + +**Derived values**: +- Open findings by severity +- Staleness: last drift scan older than 7 days + +## KPI Queries (read-only) + +### Dashboard +- Drift KPIs: counts of open findings by severity + stale drift indicator. +- Operations health: counts of active runs + failed/partial recent. +- Recent lists: latest 10 findings + latest 10 operation runs. + +### Inventory hub +- Total items +- Coverage % (restorable/total) +- Last inventory sync (status + timestamp) +- Active operations: (all active runs) + (inventory.sync active runs) + +### Operations index +- Total runs (30d) +- Active runs (queued + running) +- Failed/partial (7d) +- Avg duration (7d, terminal runs only) + +All queries must be tenant-scoped. diff --git a/specs/058-tenant-ui-polish/plan.md b/specs/058-tenant-ui-polish/plan.md new file mode 100644 index 0000000..540c767 --- /dev/null +++ b/specs/058-tenant-ui-polish/plan.md @@ -0,0 +1,164 @@ +# Implementation Plan: Tenant UI Polish (Dashboard + Inventory Hub + Operations) + +**Branch**: `058-tenant-ui-polish` | **Date**: 2026-01-20 | **Spec**: `specs/058-tenant-ui-polish/spec.md` +**Input**: Feature specification from `specs/058-tenant-ui-polish/spec.md` + +**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts. + +## Summary + +- Build a drift-first, tenant-scoped dashboard with “Needs Attention” and recent lists. +- Make Inventory a hub using a Filament cluster to provide consistent left-side sub-navigation across Items / Sync Runs / Coverage. +- Upgrade Operations index to “orders-style” with KPIs + status tabs filtering the existing `OperationRunResource` table. +- Enforce DB-only renders (and DB-only polling) and a calm UI: polling only while active runs exist, and no polling churn in modals. + +## Technical Context + + + +**Language/Version**: PHP 8.4.15 (Laravel 12.47.0) +**Primary Dependencies**: Filament v5.0.0, Livewire v4.0.1 +**Storage**: PostgreSQL +**Testing**: Pest v4 (+ PHPUnit v12 runtime) +**Target Platform**: Web application (Filament admin panel) +**Project Type**: Web (Laravel monolith) +**Performance Goals**: Dashboard/Inventory/Operations render quickly (target <2s for typical tenants) with efficient tenant-scoped queries and no N+1. +**Constraints**: DB-only for all page renders and any polling/auto-refresh; avoid UI churn in modals. +**Scale/Scope**: Tenant-scoped surfaces; KPI math on existing `operation_runs`, `findings`, inventory tables. + +## 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 for this feature (read-only, DB-only, tenant-scoped; no Graph calls added). + +## Project Structure + +### Documentation (this feature) + +```text +specs/058-tenant-ui-polish/ +├── 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 +app/ +├── Filament/ +│ ├── Clusters/ # New: Inventory cluster +│ ├── Pages/ # New/updated: tenant dashboard, inventory landing, coverage +│ ├── Resources/ # Updated: attach inventory resources to cluster; operations tabs/KPIs +│ └── Widgets/ # New/updated: KPI header widgets +├── Models/ # Existing: Tenant, OperationRun, Finding, InventoryItem, InventorySyncRun +└── Providers/Filament/ + └── AdminPanelProvider.php # Update: discoverClusters(), dashboard page class + +resources/ +└── views/ # Optional: partials/views for dashboard sections + +tests/ +└── Feature/ + ├── Monitoring/ # Existing: Operations DB-only + tenant scope tests + └── Filament/ # Existing + new: Inventory/Dashboard page tests +``` + +**Structure Decision**: Laravel monolith + Filament (v5) conventions. Implement UI changes via: +- Filament Pages (dashboard + inventory pages) +- Filament Clusters (inventory sub-navigation) +- Filament Widgets (KPI headers / recent lists) +- Filament Resource list tabs (operations index filtering) + +## Complexity Tracking + +> **Fill ONLY if Constitution Check has violations that must be justified** + +None. + +## Phase 0 — Outline & Research (complete) + +- Output: `specs/058-tenant-ui-polish/research.md` +- Key decisions captured: + - Use Filament clusters for the Inventory hub sub-navigation. + - Use Filament widgets for KPI headers. + - Enable polling only while active runs exist. + +## Phase 1 — Design & Contracts (complete) + +### Data model +- Output: `specs/058-tenant-ui-polish/data-model.md` +- No schema changes required. + +### UI contracts +- Output: `specs/058-tenant-ui-polish/contracts/ui.md` +- Output: `specs/058-tenant-ui-polish/contracts/polling.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 +- Prefer existing Filament theme CSS and hook classes; avoid publishing Filament internal views. +- No heavy assets expected; if any new panel assets are added, ensure deployment runs `php artisan filament:assets`. + +### Destructive actions +- None introduced in this feature. + +### Constitution re-check (post-design) +- ✅ Inventory-first: dashboard uses Inventory/Findings/OperationRun as last-observed state. +- ✅ Read/write separation: this feature is read-only. +- ✅ Graph contract path: no Graph calls added. +- ✅ Tenant isolation: all queries remain tenant-scoped. +- ✅ Run observability: only consumes existing `OperationRun` records; no new long-running work is introduced. +- ✅ Data minimization: no new payload storage. + +## Phase 2 — Implementation Plan (next) + +### Story 1 (P1): Drift-first tenant dashboard +- Create a custom Filament dashboard page (tenant-scoped) and wire it in `AdminPanelProvider` instead of the default `Dashboard::class`. +- Implement drift + ops KPIs and “Needs Attention” + recent lists using DB-only Eloquent queries. +- Implement conditional polling (only while active runs exist) using widget polling controls. +- Tests: + - Add DB-only coverage tests for the dashboard (no outbound HTTP; no queued jobs on render). + - Add tenant scope tests for the dashboard. + +### Story 2 (P2): Inventory becomes a hub +- Add `discoverClusters()` to `AdminPanelProvider`. +- Create `InventoryCluster` and assign `$cluster` on inventory pages/resources. +- Add a shared inventory KPI header (widget) across the cluster surfaces. +- Tests: + - Extend existing inventory page tests to assert cluster pages load and remain tenant-scoped. + +### Story 3 (P3): Operations index “orders-style” +- Update `OperationRunResource` list page to: + - Add KPI header widgets. + - Add tabs: All / Active / Succeeded / Partial / Failed. + - Enable table polling only while active runs exist. +- Tests: + - Extend operations tests to assert page renders with tabs and remains DB-only/tenant-scoped. diff --git a/specs/058-tenant-ui-polish/quickstart.md b/specs/058-tenant-ui-polish/quickstart.md new file mode 100644 index 0000000..70a0ffb --- /dev/null +++ b/specs/058-tenant-ui-polish/quickstart.md @@ -0,0 +1,27 @@ +# Quickstart — Tenant UI Polish + +## Prereqs +- Run everything via Sail. + +## Setup +- `vendor/bin/sail up -d` +- `vendor/bin/sail composer install` + +## Run tests (targeted) +- `vendor/bin/sail artisan test tests/Feature/Monitoring/OperationsDbOnlyTest.php` +- `vendor/bin/sail artisan test tests/Feature/Monitoring/OperationsTenantScopeTest.php` +- `vendor/bin/sail artisan test tests/Feature/Filament/InventoryPagesTest.php` + +When the feature is implemented, add + run: +- Dashboard DB-only + tenant scope tests (new). + +## Manual QA (tenant-scoped) +- Sign in, select a tenant. +- Visit Dashboard: verify drift/ops KPIs, needs attention, and recent lists. +- Visit Inventory cluster: Items / Sync Runs / Coverage share left sub-navigation and KPI header. +- Visit Operations (`/operations`): KPI header + tabs filter table. + +## Frontend assets +If UI changes don’t show: +- `vendor/bin/sail npm run dev` +- or `vendor/bin/sail npm run build` diff --git a/specs/058-tenant-ui-polish/research.md b/specs/058-tenant-ui-polish/research.md new file mode 100644 index 0000000..b436fe7 --- /dev/null +++ b/specs/058-tenant-ui-polish/research.md @@ -0,0 +1,66 @@ +# Research — Tenant UI Polish (Dashboard + Inventory Hub + Operations) + +## Goal +Deliver a drift-first, tenant-scoped UI polish pass that is: +- DB-only on render and on any auto-refresh. +- Calm (polling only when needed; no modal churn). +- Consistent IA (Inventory hub sub-navigation; canonical Operations). + +## Existing Code & Patterns (to reuse) + +### Operations +- Canonical list/detail already exist via `OperationRunResource` (`/operations`). +- Tenant scoping already enforced in `OperationRunResource::getEloquentQuery()`. +- Detail view already uses conditional polling with safeguards (tab hidden / modal open) via `RunDetailPolling`. + +### Inventory +- Inventory entry page exists as `InventoryLanding`. +- Inventory “Items” and “Sync Runs” are currently resources (`InventoryItemResource`, `InventorySyncRunResource`). +- Inventory sync “start surface” already follows constitution rules: authorize → create/reuse `OperationRun` → enqueue job → “View run”. + +### Monitoring DB-only + Tenant isolation tests +- Monitoring/Operations has DB-only tests and tenant scope tests. +- Inventory landing + coverage have basic smoke tests. + +## Key Decisions + +### Decision: Use Filament clusters to implement the Inventory “hub” navigation +- **Decision**: Create an Inventory cluster and attach: + - `InventoryLanding` (page) + - Inventory items resource + - Inventory sync runs resource + - `InventoryCoverage` (page) +- **Rationale**: Filament clusters are designed for “common sub-navigation between pages”, including mixing pages and resources. +- **Notes**: + - Requires enabling cluster discovery in the panel provider. + - Sub-navigation position will be set to `Start` to achieve left-side navigation. + +### Decision: Implement KPI headers as widgets (StatsOverviewWidget / TableWidget) +- **Decision**: Use Filament widgets for KPI headers on: + - Tenant dashboard (drift + ops) + - Inventory hub (inventory KPIs) + - Operations index (ops KPIs) +- **Rationale**: Widgets are first-class, composable, and can optionally poll (with `$pollingInterval`) while remaining DB-only. + +### Decision: “Calm UI” auto-refresh strategy +- **Decision**: + - Dashboard + Operations index: enable polling only while active runs exist. + - Widgets/tables: polling is disabled when no active runs exist. + - No polling inside modals. +- **Rationale**: Matches FR-012 and avoids background churn. +- **Implementation approach**: + - Use Filament polling mechanisms: + - Widgets: `$pollingInterval = null | '10s'` depending on “active runs exist”. + - Tables: enable `$table->poll('10s')` only when “active runs exist”. + +### Decision: No Graph / remote dependencies +- **Decision**: All queries for this feature are Eloquent/PostgreSQL queries. +- **Rationale**: Matches constitution and SC-005. + +## Alternatives Considered +- **Custom Blade layouts for hub navigation**: Rejected because clusters provide consistent sub-nav across resources/pages without fragile view overrides. +- **Always-on polling**: Rejected to comply with calm UI rules and avoid waste. +- **Keep `Monitoring/Operations` as canonical**: Rejected because `OperationRunResource` is already the canonical Operations surface with correct routing and detail pages. + +## Open Questions +None — all “NEEDS CLARIFICATION” items are resolved for planning. diff --git a/specs/058-tenant-ui-polish/spec.md b/specs/058-tenant-ui-polish/spec.md index 079ad1c..eed7ac4 100644 --- a/specs/058-tenant-ui-polish/spec.md +++ b/specs/058-tenant-ui-polish/spec.md @@ -5,6 +5,19 @@ # Feature Specification: Tenant UI Polish (Dashboard + Inventory Hub + Operation **Status**: Draft **Input**: User description: "Feature 058 — Tenant UI Polish: Dashboard + Inventory Hub + Operations \"Orders-style\" (v1)" +## Clarifications + +### Session 2026-01-20 + +- Q: Coverage % definition for Inventory KPI header? → A: Coverage % = Restorable / Total (Partial remains a separate chip/number; main % stays conservative) +- Q: Drift stale threshold (last scan older than X days)? → A: 7 days +- Q: Inventory KPI “Active Operations” definition? → A: Show both counts: All active runs (queued + running) and Inventory-active runs (queued + running) +- Q: How many rows in “Recent” lists by default? → A: 10 + +### Session 2026-01-21 + +- Q: Operations index "Stuck" tab in v1? -> A: No "Stuck" tab in v1 + ## User Scenarios & Testing *(mandatory)*