TenantAtlas/specs/123-operations-auto-refresh/plan.md
ahmido 4db73e872e Spec 123: operations auto-refresh pass (#149)
## Summary
- add conditional polling support for the tenantless operation run viewer and tenant review pack card
- add focused Pest coverage for active vs terminal polling behavior and related review pack access regressions
- add the full Spec Kit artifacts for Spec 123, including spec, plan, research, data model, contracts, quickstart, tasks, and checklist

## Testing
- `vendor/bin/sail artisan test --compact tests/Feature/OpsUx/RunDetailPollingStopsOnTerminalTest.php tests/Feature/Operations/TenantlessOperationRunViewerTest.php tests/Feature/ReviewPack/ReviewPackWidgetTest.php tests/Feature/ReviewPack/ReviewPackGenerationTest.php tests/Feature/ReviewPack/ReviewPackRbacTest.php`
- `vendor/bin/sail bin pint --dirty --format agent`

## Notes
- Manual QA task `T014` in the Spec Kit checklist remains to be completed outside this automated flow.
- Livewire v4.0+ compliance is unchanged.
- No panel provider changes were made; provider registration remains in `bootstrap/providers.php`.
- No global-search behavior was changed.
- No destructive actions were added or modified.
- No new Filament assets were introduced; existing deployment expectations for `php artisan filament:assets` remain unchanged.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #149
2026-03-08 11:11:26 +00:00

162 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Implementation Plan: Operations Auto-Refresh Pass
**Branch**: `[123-operations-auto-refresh]` | **Date**: 2026-03-08 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/123-operations-auto-refresh/spec.md`
**Note**: This plan is filled in by the `/speckit.plan` workflow.
## Summary
Add conditional auto-refresh to the canonical tenantless operation run viewer and intentionally reusable tenant-scoped review pack card surfaces by reusing existing product polling patterns instead of inventing new infrastructure. The run viewer will stay aligned with the shared run-detail polling helper and its existing hidden-tab / modal-open safeguards, while the embedded review pack widget will emit a simple `10s` Livewire polling interval only when the latest review pack is in an active generation state.
## Technical Context
**Language/Version**: PHP 8.4 runtime target on Laravel 12 code conventions; Composer constraint `php:^8.2`
**Primary Dependencies**: Laravel 12, Filament v5.2.1, Livewire v4, Pest v4, Laravel Sail
**Storage**: PostgreSQL primary app database
**Testing**: Pest feature tests run through `vendor/bin/sail artisan test --compact`
**Target Platform**: Web application rendered through Filament panels on Laravel Sail / containerized deployment
**Project Type**: Single Laravel web application
**Performance Goals**: Active monitoring surfaces should refresh automatically without manual input while avoiding unnecessary polling once work is terminal
**Constraints**: Preserve DB-only render behavior for monitoring surfaces; no WebSockets, no new backend events, no global polling rewrite, no polling on terminal states
**Scale/Scope**: Two existing UI surfaces, no schema changes, no dependency changes, targeted regression coverage only
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
- **Inventory-first**: PASS — no inventory or snapshot semantics change.
- **Read/write separation**: PASS — no new write workflow is introduced; only passive refresh behavior changes.
- **Graph contract path**: PASS — no Graph calls or contract registry changes are involved.
- **Deterministic capabilities**: PASS — no capability derivation changes.
- **RBAC-UX plane separation**: PASS — `/admin/operations/{run}` remains a canonical Monitoring route and the intentionally reusable tenant-scoped review widget remains tenant-plane only on every host surface, with existing authorization rules unchanged.
- **Workspace isolation**: PASS — the tenantless operation viewer continues to rely on existing workspace membership checks and referenced-tenant entitlement checks for tenant-bound runs.
- **Destructive confirmations**: PASS — no new destructive actions are added.
- **Global search safety**: PASS — feature does not touch global search.
- **Tenant isolation**: PASS — review pack polling remains tenant-scoped and uses existing access checks.
- **Run observability**: PASS — existing `OperationRun` records remain the sole source for operation progress; no new run type or lifecycle mutation path is introduced.
- **Ops-UX 3-surface feedback**: PASS — queued toast, progress surfaces, and terminal notification behavior are unchanged.
- **Ops-UX lifecycle ownership**: PASS — this feature reads run state only; `OperationRunService` remains the only lifecycle transition owner.
- **Ops-UX summary counts**: PASS — unchanged.
- **Ops-UX guards**: PASS — existing helper guard coverage is reused and extended where needed.
- **Ops-UX system runs**: PASS — unchanged.
- **Automation / idempotency**: PASS — unchanged.
- **Data minimization / safe logging**: PASS — unchanged.
- **Badge semantics (BADGE-001)**: PASS — existing badge mappings stay centralized; polling only re-renders them.
- **Filament Action Surface Contract**: PASS WITH EXEMPTION — affected surfaces change passive refresh behavior only, not action definitions.
- **Filament UX-001**: PASS WITH EXEMPTION — no layout or information-architecture changes are introduced.
- **Livewire v4.0+ compliance**: PASS — Filament v5 / Livewire v4 stack remains unchanged.
- **Provider registration location**: PASS — no panel-provider changes; Laravel 12 keeps providers in `bootstrap/providers.php`.
## Phase 0 — Research Summary
Research findings are recorded in [research.md](./research.md).
- Reuse `App\Support\OpsUx\RunDetailPolling::interval()` for tenantless run detail behavior instead of introducing a second run-detail polling policy.
- Preserve the existing run-detail suppression guards for hidden browser tabs and mounted Filament actions.
- Treat review-pack `queued` and `generating` as the only active widget states; `ready`, `failed`, `expired`, and empty state are terminal/non-polling.
- Attach review-pack polling at the widget Blade root using the same `pollingInterval``wire:poll.{interval}` pattern already used by lightweight dashboard widgets.
- Extend existing Pest coverage rather than building new test infrastructure.
## Phase 1 — Design & Contracts
### Data Model
Design details are recorded in [data-model.md](./data-model.md).
Key design points:
- No schema changes are required.
- `OperationRun` remains the source of truth for run-detail polling decisions.
- `ReviewPack` remains the source of truth for review-pack-card polling decisions.
- Polling state is derived view state (`interval string | null`), not persisted state.
### Contracts
Internal UI behavior contracts are recorded in [contracts/polling-contracts.yaml](./contracts/polling-contracts.yaml).
Contract scope:
- Tenantless operation run viewer at `/admin/operations/{run}`
- Intentionally reusable tenant-scoped embedded `TenantReviewPackCard` widget surfaces (component-scoped; no standalone route is owned by the widget itself)
### Quickstart
Implementation and verification steps are recorded in [quickstart.md](./quickstart.md).
### Post-Design Constitution Re-check
- **Inventory-first**: PASS — no data-ownership boundary changes.
- **Read/write separation**: PASS — polling remains read-only.
- **Graph contract path**: PASS — no remote integrations added.
- **RBAC-UX**: PASS — existing 404/403 behavior and capability checks remain authoritative.
- **Workspace isolation**: PASS — tenantless run viewer continues to authorize against the run workspace and referenced tenant scope when the run is tenant-bound.
- **Tenant isolation**: PASS — review-pack-card polling is based on the current tenants latest pack only.
- **Run observability**: PASS — `OperationRun` reuse remains intact; no inline work added to render surfaces.
- **Ops-UX lifecycle ownership**: PASS — plan introduces no direct `status` / `outcome` mutation path.
- **BADGE-001**: PASS — no new badge semantics introduced.
- **Filament Action Surface Contract**: PASS WITH EXEMPTION — no action-surface mutation.
- **UX-001**: PASS WITH EXEMPTION — no layout change required for passive refresh.
## Project Structure
### Documentation (this feature)
```text
specs/123-operations-auto-refresh/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── polling-contracts.yaml
└── tasks.md
```
### Source Code (repository root)
```text
app/
├── Filament/
│ ├── Pages/Operations/TenantlessOperationRunViewer.php
│ ├── Resources/OperationRunResource.php
│ └── Widgets/
│ ├── Dashboard/NeedsAttention.php
│ └── Tenant/TenantReviewPackCard.php
├── Models/
│ ├── OperationRun.php
│ └── ReviewPack.php
├── Services/
│ └── ReviewPackService.php
└── Support/OpsUx/
├── ActiveRuns.php
├── OperationStatusNormalizer.php
└── RunDetailPolling.php
resources/views/
├── filament/pages/operations/tenantless-operation-run-viewer.blade.php
├── filament/widgets/dashboard/needs-attention.blade.php
└── filament/widgets/tenant/tenant-review-pack-card.blade.php
tests/Feature/
├── Operations/TenantlessOperationRunViewerTest.php
├── OpsUx/RunDetailPollingStopsOnTerminalTest.php
└── ReviewPack/ReviewPackWidgetTest.php
```
**Structure Decision**: Keep the implementation inside the existing Laravel / Filament structure. Reuse current polling helpers and Blade widget patterns in place, with targeted updates limited to the two affected surfaces and their directly related tests.
## Testing Strategy
- Extend helper-level coverage for run-detail active-versus-terminal polling behavior only if the shared helper changes.
- Add page/widget assertions that active surfaces emit polling and terminal surfaces do not.
- Keep verification targeted to:
- `tests/Feature/OpsUx/RunDetailPollingStopsOnTerminalTest.php`
- `tests/Feature/Operations/TenantlessOperationRunViewerTest.php`
- `tests/Feature/ReviewPack/ReviewPackWidgetTest.php`
- `tests/Feature/ReviewPack/ReviewPackGenerationTest.php`
- `tests/Feature/ReviewPack/ReviewPackRbacTest.php` for unchanged tenant-scope access regression coverage
- Manual QA will cover one active and one terminal example for each affected surface.
## Complexity Tracking
No constitution violations or complexity exemptions are required for this plan.