TenantAtlas/specs/123-operations-auto-refresh/data-model.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

99 lines
3.3 KiB
Markdown

# Data Model — Operations Auto-Refresh Pass
## Overview
This feature does not add new tables or columns. It reuses existing persisted state to decide whether two UI surfaces should continue polling.
## Entities
### OperationRun
- **Purpose**: Canonical record for queued, running, and completed operational work shown in Monitoring → Operations.
- **Relevant fields**:
- `id`
- `workspace_id`
- `tenant_id` (nullable for tenantless/canonical monitoring)
- `type`
- `status`
- `outcome`
- `context`
- `summary_counts`
- `failure_summary`
- `created_at`
- `started_at`
- `completed_at`
- **Relationships**:
- Belongs to `Workspace`
- Belongs to `Tenant` (optional)
- Belongs to initiating `User` (optional)
- **Polling rule**:
- Poll while UX-normalized status is `queued` or `running`
- Stop polling for normalized terminal states such as `succeeded`, `partial`, or `failed`
- **Derived constraints**:
- Polling on run-detail surfaces must continue to respect hidden-tab and mounted-action guards
- No direct lifecycle mutation is added; `OperationRunService` remains the only lifecycle transition owner
### ReviewPack
- **Purpose**: Persisted output of tenant review pack generation for a tenant-scoped admin surface.
- **Relevant fields**:
- `id`
- `workspace_id`
- `tenant_id`
- `operation_run_id`
- `initiated_by_user_id`
- `status`
- `options`
- `summary`
- `generated_at`
- `expires_at`
- `file_path`
- `file_disk`
- `file_size`
- `created_at`
- `updated_at`
- **Relationships**:
- Belongs to `Workspace`
- Belongs to `Tenant`
- Belongs to `OperationRun`
- Belongs to initiating `User`
- **Polling rule**:
- Poll while `status` is `queued` or `generating`
- Stop polling when `status` is `ready`, `failed`, or `expired`
- Do not poll when no review pack exists for the tenant
## Derived View State
### Run detail polling state
- **Source**: `OperationRun` + `RunDetailPolling::interval()`
- **Output**: `1s`, `5s`, `10s`, or `null`
- **Rules**:
- `null` when the run is terminal
- `null` when the tab is hidden
- `null` when Filament action modals are mounted
### Review pack card polling state
- **Source**: latest `ReviewPack` for the current tenant
- **Output**: `10s` or `null`
- **Rules**:
- `10s` when the latest pack is `queued` or `generating`
- `null` otherwise
## State Transitions
### OperationRun lifecycle relevant to polling
1. `queued` → active polling enabled
2. `running` → active polling enabled
3. `completed` + terminal outcome (`succeeded`, `failed`, `partially_succeeded`) → polling disabled
4. Any unrecognized or missing status normalization → treated as non-active for polling decisions
### ReviewPack lifecycle relevant to polling
1. `queued` → polling enabled
2. `generating` → polling enabled
3. `ready` → polling disabled
4. `failed` → polling disabled
5. `expired` → polling disabled
## Validation Rules
- Polling must never start for unauthorized users; existing page and widget access checks remain authoritative.
- Polling must stop automatically once terminal state is reached.
- Polling decisions must be derived from persisted state only; no external API call is required during render.
- Terminal-state rendering must remain stable and must not trigger repeated refresh loops.