TenantAtlas/app/Services/PermissionPosture/PostureScoreCalculator.php
Ahmed Darrazi 222a7e0a97 feat(104): implement Provider Permission Posture
- T001-T014: Foundation - StoredReport model/migration, Finding resolved
  lifecycle, badge mappings (resolved status, permission_posture type),
  OperationCatalog + AlertRule constants
- T015-T022: US1 - PermissionPostureFindingGenerator with fingerprint-based
  idempotent upsert, severity from feature-impact count, auto-resolve on
  grant, auto-reopen on revoke, error findings (FR-015), stale finding
  cleanup; GeneratePermissionPostureFindingsJob dispatched from health check;
  PostureResult VO + PostureScoreCalculator
- T023-T026: US2+US4 - Stored report payload validation, temporal ordering,
  polymorphic reusability, score accuracy acceptance tests
- T027-T029: US3 - EvaluateAlertsJob.permissionMissingEvents() wired into
  alert pipeline, AlertRuleResource event type option, cooldown/dedupe tests
- T030-T034: Polish - PruneStoredReportsCommand with config retention,
  scheduled daily, end-to-end integration test, Pint clean

UI bug fixes found during testing:
- FindingResource: hide Diff section for non-drift findings
- TenantRequiredPermissions: fix re-run verification link
- tenant-required-permissions.blade.php: preserve details open state

70 tests (50 PermissionPosture + 20 FindingResolved/Badge/Alert), 216 assertions
2026-02-21 23:31:03 +01:00

42 lines
1008 B
PHP
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.

<?php
declare(strict_types=1);
namespace App\Services\PermissionPosture;
/**
* Calculates a normalized posture score (0100) from a permission comparison result.
*
* Pure function: no side effects, no DB access.
*/
final class PostureScoreCalculator
{
/**
* @param array{permissions: array<int, array{status: string, ...}>, ...} $permissionComparison
*/
public function calculate(array $permissionComparison): int
{
$permissions = $permissionComparison['permissions'] ?? [];
if (! is_array($permissions)) {
return 100;
}
$requiredCount = count($permissions);
if ($requiredCount === 0) {
return 100;
}
$grantedCount = 0;
foreach ($permissions as $permission) {
if (is_array($permission) && ($permission['status'] ?? null) === 'granted') {
$grantedCount++;
}
}
return (int) round($grantedCount / $requiredCount * 100);
}
}