TenantAtlas/specs/104-provider-permission-posture/quickstart.md
ahmido ef380b67d1 feat(104): Provider Permission Posture (#127)
Implements Spec 104: Provider Permission Posture.

What changed
- Generates permission posture findings after each tenant permission compare (queued)
- Stores immutable posture snapshots as StoredReports (JSONB payload)
- Adds global Finding resolved lifecycle (`resolved_at`, `resolved_reason`) with `resolve()` / `reopen()`
- Adds alert pipeline event type `permission_missing` (Alerts v1) and Filament option for Alert Rules
- Adds retention pruning command + daily schedule for StoredReports
- Adds badge mappings for `resolved` finding status and `permission_posture` finding type

UX fixes discovered during manual verification
- Hide “Diff” section for non-drift findings (only drift findings show diff)
- Required Permissions page: “Re-run verification” now links to Tenant view (not onboarding)
- Preserve Technical Details `<details>` open state across Livewire re-renders (Alpine state)

Verification
- Ran `vendor/bin/sail artisan test --compact --filter=PermissionPosture` (50 tests)
- Ran `vendor/bin/sail artisan test --compact --filter="FindingResolved|FindingBadge|PermissionMissingAlert"` (20 tests)
- Ran `vendor/bin/sail bin pint --dirty`

Filament v5 / Livewire v4 compliance
- Filament v5 + Livewire v4: no Livewire v3 usage.

Panel provider registration (Laravel 11+)
- No new panels added. Existing panel providers remain registered via `bootstrap/providers.php`.

Global search rule
- No changes to global-searchable resources.

Destructive actions
- No new destructive Filament actions were added in this PR.

Assets / deploy notes
- No new Filament assets registered. Existing deploy step `php artisan filament:assets` remains unchanged.

Test coverage
- New/updated Pest feature tests cover generator behavior, job integration, alerting, retention pruning, and resolved lifecycle.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #127
2026-02-21 22:32:52 +00:00

3.3 KiB

Quickstart: Provider Permission Posture (Spec 104)

Branch: 104-provider-permission-posture

Prerequisites

  • Laravel Sail running (vendor/bin/sail up -d)
  • Database migrated (vendor/bin/sail artisan migrate)
  • At least one tenant with a provider connection configured

New Files Created (Implementation Order)

Phase A — Foundation (StoredReports + Finding model extensions)

database/migrations/XXXX_create_stored_reports_table.php
database/migrations/XXXX_add_resolved_to_findings_table.php
app/Models/StoredReport.php
database/factories/StoredReportFactory.php

Phase B — Core Generator

app/Services/PermissionPosture/PostureScoreCalculator.php
app/Services/PermissionPosture/PermissionPostureFindingGenerator.php

Phase C — Job + Health Check Hook

app/Jobs/GeneratePermissionPostureFindingsJob.php

Modified: app/Jobs/ProviderConnectionHealthCheckJob.php (dispatch hook)

Phase D — Alerts Integration

Modified: app/Models/AlertRule.php (new EVENT constant) Modified: app/Jobs/Alerts/EvaluateAlertsJob.php (new event method)

Phase E — Badge + UI Integration

Modified: app/Support/Badges/Domains/FindingStatusBadge.php (resolved badge) Modified: app/Support/OperationCatalog.php (new type constant)

Phase F — Retention

app/Console/Commands/PruneStoredReportsCommand.php

Modified: routes/console.php (schedule)

Modified Files Summary

File Change
app/Models/Finding.php Add STATUS_RESOLVED, FINDING_TYPE_PERMISSION_POSTURE, resolve(), reopen() methods, resolved_at cast
app/Models/AlertRule.php Add EVENT_PERMISSION_MISSING constant
app/Support/OperationCatalog.php Add TYPE_PERMISSION_POSTURE_CHECK constant
app/Support/Badges/Domains/FindingStatusBadge.php Add resolved badge mapping
app/Jobs/ProviderConnectionHealthCheckJob.php Dispatch posture job after compare()
app/Jobs/Alerts/EvaluateAlertsJob.php Add permissionMissingEvents() method
database/factories/FindingFactory.php Add permissionPosture() and resolved() states
routes/console.php Schedule stored-reports:prune daily

Running Tests

# All Spec 104 tests
vendor/bin/sail artisan test --compact --filter=PermissionPosture

# Specific test files
vendor/bin/sail artisan test --compact tests/Feature/PermissionPosture/PostureScoreCalculatorTest.php
vendor/bin/sail artisan test --compact tests/Feature/PermissionPosture/PermissionPostureFindingGeneratorTest.php
vendor/bin/sail artisan test --compact tests/Feature/PermissionPosture/GeneratePermissionPostureFindingsJobTest.php
vendor/bin/sail artisan test --compact tests/Feature/PermissionPosture/StoredReportTest.php
vendor/bin/sail artisan test --compact tests/Feature/Alerts/PermissionMissingAlertTest.php

Key Design Decisions

  1. Trigger: Event-driven from health check job (not scheduled independently)
  2. resolved status: Global to all finding types (migration adds columns to findings table)
  3. Re-open: Resolved findings are re-opened (not archived+recreated)
  4. Auto-resolve scope: Both new and acknowledged findings auto-resolve when permission is granted
  5. StoredReport: Generic, reusable table (not permission-posture-specific)
  6. Severity: Derived from feature count in config registry (deterministic)