TenantAtlas/apps/platform/app/Support/Operations/Actionability/OperationRunActionabilityRegistry.php
Ahmed Darrazi 0329cb5420
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m0s
feat: implement operation run actionability system
2026-06-08 15:19:55 +02:00

138 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\Operations\Actionability;
use App\Support\OperationCatalog;
final class OperationRunActionabilityRegistry
{
/**
* @return array<string, OperationRunActionabilityPolicyDefinition>
*/
public function definitions(): array
{
$definitions = [];
$add = static function (OperationRunActionabilityPolicyDefinition $definition) use (&$definitions): void {
$definitions[$definition->canonicalType] = $definition;
};
$add(new OperationRunActionabilityPolicyDefinition(
canonicalType: 'provider.connection.check',
policyIdentifier: 'provider_connection_check_current_state_v1',
kind: 'provider_connection',
supersededByCanonicalTypes: ['provider.connection.check'],
matchContextKeys: ['provider_connection_id', 'provider'],
));
foreach ([
'inventory.sync',
'policy.sync',
'policy.snapshot',
'policy.export',
'directory.groups.sync',
'directory.role_definitions.sync',
'compliance.snapshot',
'permission.posture.check',
'entra.admin_roles.scan',
'rbac.health_check',
'tenant.sync',
'assignments.fetch',
'alerts.evaluate',
'alerts.deliver',
'ops.reconcile_adapter_runs',
] as $type) {
$add(new OperationRunActionabilityPolicyDefinition(
canonicalType: $type,
policyIdentifier: 'repeatable_later_success_v1',
kind: 'repeatable',
supersededByCanonicalTypes: [$type],
matchContextKeys: ['selection_hash', 'provider_connection_id', 'provider'],
));
}
foreach ([
'baseline.capture',
'baseline.compare',
'tenant.evidence.snapshot.generate',
'environment.review.compose',
'environment.review_pack.generate',
'backup_set.update',
'backup.schedule.execute',
'backup.schedule.retention',
] as $type) {
$add(new OperationRunActionabilityPolicyDefinition(
canonicalType: $type,
policyIdentifier: 'artifact_or_later_success_v1',
kind: 'artifact_or_later_success',
supersededByCanonicalTypes: [$type],
matchContextKeys: ['baseline_profile_id', 'backup_set_id', 'backup_schedule_id', 'selection_hash'],
));
}
foreach ([
'policy.delete',
'policy.restore',
'backup_set.archive',
'backup_set.restore',
'backup_set.delete',
'backup.schedule.purge',
'restore.execute',
'promotion.execute',
'assignments.restore',
'restore_run.delete',
'restore_run.restore',
'restore_run.force_delete',
'policy_version.prune',
'policy_version.restore',
'policy_version.force_delete',
] as $type) {
$add(new OperationRunActionabilityPolicyDefinition(
canonicalType: $type,
policyIdentifier: 'high_risk_manual_review_v1',
kind: 'manual_review',
));
}
return $definitions;
}
public function forCanonicalType(string $canonicalType): ?OperationRunActionabilityPolicyDefinition
{
return $this->definitions()[$canonicalType] ?? null;
}
/**
* @return list<string>
*/
public function coveredCanonicalTypes(): array
{
return array_values(array_unique(array_keys($this->definitions())));
}
/**
* @return list<string>
*/
public function uncoveredCanonicalTypes(): array
{
return array_values(array_diff(
array_keys(OperationCatalog::canonicalInventory()),
$this->coveredCanonicalTypes(),
));
}
/**
* @return list<string>
*/
public function canonicalTypesWithLaterSuccessPolicy(): array
{
return collect($this->definitions())
->flatMap(static fn (OperationRunActionabilityPolicyDefinition $definition): array => $definition->supersededByCanonicalTypes)
->unique()
->values()
->all();
}
}