Fix tenant dashboard 500 (missing BaselineCompareRun) #125
@ -4,9 +4,9 @@
|
||||
|
||||
namespace App\Filament\Widgets\Dashboard;
|
||||
|
||||
use App\Models\BaselineCompareRun;
|
||||
use App\Models\BaselineTenantAssignment;
|
||||
use App\Models\Finding;
|
||||
use App\Models\OperationRun;
|
||||
use App\Models\Tenant;
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\Widgets\Widget;
|
||||
@ -69,11 +69,12 @@ protected function getViewData(): array
|
||||
->where('severity', Finding::SEVERITY_LOW)
|
||||
->count();
|
||||
|
||||
$latestRun = BaselineCompareRun::query()
|
||||
$latestRun = OperationRun::query()
|
||||
->where('tenant_id', $tenant->getKey())
|
||||
->where('baseline_profile_id', $profile->getKey())
|
||||
->whereNotNull('finished_at')
|
||||
->latest('finished_at')
|
||||
->where('type', 'baseline_compare')
|
||||
->where('context->baseline_profile_id', (string) $profile->getKey())
|
||||
->whereNotNull('completed_at')
|
||||
->latest('completed_at')
|
||||
->first();
|
||||
|
||||
return [
|
||||
|
||||
26
specs/feat/700-bugfix/plan.md
Normal file
26
specs/feat/700-bugfix/plan.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Implementation Plan: BaselineCompareRun model bugfix
|
||||
|
||||
**Branch**: `feat/700-bugfix` | **Date**: 2026-02-20 | **Spec**: `specs/feat/700-bugfix/spec.md`
|
||||
|
||||
## Summary
|
||||
|
||||
Fix runtime crash caused by a missing Eloquent model referenced by a Filament dashboard widget.
|
||||
|
||||
## Technical Context
|
||||
|
||||
- PHP 8.4.x, Laravel 12
|
||||
- Filament v5, Livewire v4
|
||||
- PostgreSQL (Sail locally)
|
||||
- Tests: Pest v4 (`vendor/bin/sail artisan test --compact`)
|
||||
|
||||
## Approach
|
||||
|
||||
1. Identify intended storage for baseline compare runs:
|
||||
- If a `baseline_compare_runs` table already exists, implement `App\Models\BaselineCompareRun` mapped to it.
|
||||
- If not, align the widget to an existing persistence type (likely `OperationRun`) without changing UX.
|
||||
2. Add a regression test that exercises the tenant dashboard route and asserts a successful response.
|
||||
3. Run Pint on dirty files and run the focused test.
|
||||
|
||||
## Risks
|
||||
|
||||
- Introducing a new model without an existing table could still fail at runtime. Prefer minimal, compatibility-first changes.
|
||||
29
specs/feat/700-bugfix/spec.md
Normal file
29
specs/feat/700-bugfix/spec.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Bugfix Specification: BaselineCompareRun missing model
|
||||
|
||||
**Branch**: `feat/700-bugfix`
|
||||
**Created**: 2026-02-20
|
||||
**Status**: Ready
|
||||
|
||||
## Problem
|
||||
|
||||
Navigating to the tenant dashboard (`/admin/t/{tenant}`) throws an Internal Server Error:
|
||||
|
||||
- `Class "App\Models\BaselineCompareRun" not found`
|
||||
|
||||
The stack trace points to the dashboard widget `app/Filament/Widgets/Dashboard/BaselineCompareNow.php`.
|
||||
|
||||
## Goal
|
||||
|
||||
- Tenant dashboard loads successfully.
|
||||
- Baseline compare widget can safely query baseline compare run state without a fatal error.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- No UX redesign.
|
||||
- No new baseline-compare workflow features beyond restoring runtime stability.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Visiting `/admin/t/{tenant}` does not throw a 500.
|
||||
- The widget renders even when there are no baseline compare runs.
|
||||
- A focused automated test covers the regression.
|
||||
20
specs/feat/700-bugfix/tasks.md
Normal file
20
specs/feat/700-bugfix/tasks.md
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
description: "Tasks for feat/700-bugfix (BaselineCompareRun missing model)"
|
||||
---
|
||||
|
||||
# Tasks: feat/700-bugfix
|
||||
|
||||
**Input**: `specs/feat/700-bugfix/spec.md` and `specs/feat/700-bugfix/plan.md`
|
||||
|
||||
## Setup
|
||||
- [X] T001 Confirm whether baseline compare runs table exists
|
||||
|
||||
## Tests (TDD)
|
||||
- [X] T010 Add regression test for tenant dashboard (no 500)
|
||||
|
||||
## Core
|
||||
- [X] T020 Fix missing BaselineCompareRun reference (model or widget)
|
||||
|
||||
## Validation
|
||||
- [X] T030 Run Pint (dirty)
|
||||
- [X] T040 Run focused tests via Sail
|
||||
46
tests/Feature/Filament/BaselineCompareNowWidgetTest.php
Normal file
46
tests/Feature/Filament/BaselineCompareNowWidgetTest.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Filament\Pages\TenantDashboard;
|
||||
use App\Models\BaselineProfile;
|
||||
use App\Models\BaselineTenantAssignment;
|
||||
use App\Models\OperationRun;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
it('renders the tenant dashboard when a baseline assignment exists (regression: missing BaselineCompareRun model)', function (): void {
|
||||
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
||||
|
||||
$profile = BaselineProfile::factory()->create([
|
||||
'workspace_id' => (int) $tenant->workspace_id,
|
||||
'name' => 'Baseline A',
|
||||
]);
|
||||
|
||||
BaselineTenantAssignment::factory()->create([
|
||||
'workspace_id' => (int) $tenant->workspace_id,
|
||||
'tenant_id' => (int) $tenant->getKey(),
|
||||
'baseline_profile_id' => (int) $profile->getKey(),
|
||||
]);
|
||||
|
||||
OperationRun::factory()->create([
|
||||
'tenant_id' => (int) $tenant->getKey(),
|
||||
'workspace_id' => (int) $tenant->workspace_id,
|
||||
'type' => 'baseline_compare',
|
||||
'status' => 'completed',
|
||||
'outcome' => 'succeeded',
|
||||
'initiator_name' => 'System',
|
||||
'context' => [
|
||||
'baseline_profile_id' => (int) $profile->getKey(),
|
||||
],
|
||||
'completed_at' => now()->subDay(),
|
||||
]);
|
||||
|
||||
$this->actingAs($user)
|
||||
->get(TenantDashboard::getUrl(tenant: $tenant))
|
||||
->assertOk()
|
||||
->assertSee('Baseline Governance')
|
||||
->assertSee('Baseline A')
|
||||
->assertSee('No open drift — baseline compliant');
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user