*/ public static function labels(): array { $labels = []; foreach (self::operationAliases() as $alias) { $labels[$alias->rawValue] = self::canonicalDefinitions()[$alias->canonicalCode]->displayLabel; } return $labels; } /** * @return array */ public static function canonicalInventory(): array { $inventory = []; foreach (self::canonicalDefinitions() as $canonicalCode => $definition) { $inventory[$canonicalCode] = $definition->toArray(); } return $inventory; } public static function label(string $operationType): string { $operationType = trim($operationType); if ($operationType === '') { return 'Operation'; } return self::resolve($operationType)->canonical->displayLabel; } public static function expectedDurationSeconds(string $operationType): ?int { return self::resolve($operationType)->canonical->expectedDurationSeconds; } /** * @return array */ public static function allowedSummaryKeys(): array { return OperationSummaryKeys::all(); } public static function governanceArtifactFamily(string $operationType): ?string { return self::resolve($operationType)->canonical->artifactFamily; } public static function isGovernanceArtifactOperation(string $operationType): bool { return self::governanceArtifactFamily($operationType) !== null; } public static function supportsOperatorExplanation(string $operationType): bool { return self::resolve($operationType)->canonical->supportsOperatorExplanation; } public static function canonicalCode(string $operationType): string { return self::resolve($operationType)->canonical->canonicalCode; } /** * @return list */ public static function canonicalNouns(): array { return ['operation_type']; } public static function ownershipDescriptor(?PlatformVocabularyGlossary $glossary = null): RegistryOwnershipDescriptor { $glossary ??= app(PlatformVocabularyGlossary::class); return $glossary->registry('operation_catalog') ?? RegistryOwnershipDescriptor::fromArray([ 'registry_key' => 'operation_catalog', 'boundary_classification' => PlatformVocabularyGlossary::BOUNDARY_PLATFORM_CORE, 'owner_layer' => PlatformVocabularyGlossary::OWNER_PLATFORM_CORE, 'source_class_or_file' => self::class, 'canonical_nouns' => self::canonicalNouns(), 'allowed_consumers' => ['monitoring', 'reporting', 'launch_surfaces', 'audit'], 'compatibility_notes' => 'Resolves canonical operation meaning from historical storage values without treating every stored raw string as equally canonical.', ]); } public static function boundaryClassification(?PlatformVocabularyGlossary $glossary = null): string { return self::ownershipDescriptor($glossary)->boundaryClassification; } /** * @return list */ public static function rawValuesForCanonical(string $canonicalCode): array { return array_values(array_map( static fn (OperationTypeAlias $alias): string => $alias->rawValue, array_filter( self::operationAliases(), static fn (OperationTypeAlias $alias): bool => $alias->canonicalCode === trim($canonicalCode), ), )); } /** * @param iterable|null $types * @return array */ public static function filterOptions(?iterable $types = null): array { $values = collect($types ?? array_keys(self::labels())) ->filter(static fn (mixed $type): bool => is_string($type) && trim($type) !== '') ->map(static fn (string $type): string => trim($type)) ->mapWithKeys(static fn (string $type): array => [self::canonicalCode($type) => self::label($type)]) ->sortBy(static fn (string $label): string => $label) ->all(); return $values; } /** * @return array */ public static function aliasInventory(): array { $inventory = []; foreach (self::operationAliases() as $alias) { $inventory[$alias->rawValue] = $alias->retirementMetadata(); } return $inventory; } public static function resolve(string $operationType): OperationTypeResolution { $operationType = trim($operationType); $aliases = self::operationAliases(); $matchedAlias = collect($aliases) ->first(static fn (OperationTypeAlias $alias): bool => $alias->rawValue === $operationType); if ($matchedAlias instanceof OperationTypeAlias) { return new OperationTypeResolution( rawValue: $operationType, canonical: self::canonicalDefinitions()[$matchedAlias->canonicalCode], aliasesConsidered: array_values(array_filter( $aliases, static fn (OperationTypeAlias $alias): bool => $alias->canonicalCode === $matchedAlias->canonicalCode, )), aliasStatus: $matchedAlias->aliasStatus, wasLegacyAlias: $matchedAlias->aliasStatus !== 'canonical', ); } return new OperationTypeResolution( rawValue: $operationType, canonical: new CanonicalOperationType( canonicalCode: $operationType, domainKey: null, artifactFamily: null, displayLabel: 'Unknown operation', supportsOperatorExplanation: false, expectedDurationSeconds: null, ), aliasesConsidered: [], aliasStatus: 'unknown', wasLegacyAlias: false, ); } /** * @return array */ private static function canonicalDefinitions(): array { return [ 'policy.sync' => new CanonicalOperationType('policy.sync', 'intune', null, 'Policy sync', false, 90), 'policy.snapshot' => new CanonicalOperationType('policy.snapshot', 'intune', null, 'Policy snapshot', false, 120), 'policy.delete' => new CanonicalOperationType('policy.delete', 'intune', null, 'Delete policies'), 'policy.restore' => new CanonicalOperationType('policy.restore', 'intune', null, 'Restore policies'), 'policy.export' => new CanonicalOperationType('policy.export', 'intune', null, 'Export policies to backup', false, 120), 'provider.connection.check' => new CanonicalOperationType('provider.connection.check', 'intune', null, 'Provider connection check', false, 30), 'inventory.sync' => new CanonicalOperationType('inventory.sync', 'intune', null, 'Inventory sync', false, 180), 'compliance.snapshot' => new CanonicalOperationType('compliance.snapshot', 'intune', null, 'Compliance snapshot', false, 180), 'directory.groups.sync' => new CanonicalOperationType('directory.groups.sync', 'entra', null, 'Directory groups sync', false, 120), 'backup_set.update' => new CanonicalOperationType('backup_set.update', 'intune', null, 'Backup set update'), 'backup_set.archive' => new CanonicalOperationType('backup_set.archive', 'intune', null, 'Archive backup sets'), 'backup_set.restore' => new CanonicalOperationType('backup_set.restore', 'intune', null, 'Restore backup sets'), 'backup_set.delete' => new CanonicalOperationType('backup_set.delete', 'intune', null, 'Delete backup sets'), 'backup.schedule.execute' => new CanonicalOperationType('backup.schedule.execute', 'intune', null, 'Backup schedule run'), 'backup.schedule.retention' => new CanonicalOperationType('backup.schedule.retention', 'intune', null, 'Backup schedule retention'), 'backup.schedule.purge' => new CanonicalOperationType('backup.schedule.purge', 'intune', null, 'Backup schedule purge'), 'restore.execute' => new CanonicalOperationType('restore.execute', 'intune', null, 'Restore execution'), 'assignments.fetch' => new CanonicalOperationType('assignments.fetch', 'intune', null, 'Assignment fetch', false, 60), 'assignments.restore' => new CanonicalOperationType('assignments.restore', 'intune', null, 'Assignment restore', false, 60), 'ops.reconcile_adapter_runs' => new CanonicalOperationType('ops.reconcile_adapter_runs', 'platform_foundation', null, 'Reconcile adapter runs', false, 120), 'directory.role_definitions.sync' => new CanonicalOperationType('directory.role_definitions.sync', 'entra', null, 'Role definitions sync'), 'restore_run.delete' => new CanonicalOperationType('restore_run.delete', 'intune', null, 'Delete restore runs'), 'restore_run.restore' => new CanonicalOperationType('restore_run.restore', 'intune', null, 'Restore restore runs'), 'restore_run.force_delete' => new CanonicalOperationType('restore_run.force_delete', 'intune', null, 'Force delete restore runs'), 'tenant.sync' => new CanonicalOperationType('tenant.sync', 'platform_foundation', null, 'Tenant sync'), 'policy_version.prune' => new CanonicalOperationType('policy_version.prune', 'intune', null, 'Prune policy versions'), 'policy_version.restore' => new CanonicalOperationType('policy_version.restore', 'intune', null, 'Restore policy versions'), 'policy_version.force_delete' => new CanonicalOperationType('policy_version.force_delete', 'intune', null, 'Delete policy versions'), 'alerts.evaluate' => new CanonicalOperationType('alerts.evaluate', 'platform_foundation', null, 'Alerts evaluation', false, 120), 'alerts.deliver' => new CanonicalOperationType('alerts.deliver', 'platform_foundation', null, 'Alerts delivery', false, 120), 'baseline.capture' => new CanonicalOperationType('baseline.capture', 'platform_foundation', 'baseline_snapshot', 'Baseline capture', true, 120), 'baseline.compare' => new CanonicalOperationType('baseline.compare', 'platform_foundation', null, 'Baseline compare', true, 120), 'permission.posture.check' => new CanonicalOperationType('permission.posture.check', 'platform_foundation', null, 'Permission posture check', false, 30), 'entra.admin_roles.scan' => new CanonicalOperationType('entra.admin_roles.scan', 'entra', null, 'Entra admin roles scan', false, 60), 'tenant.review_pack.generate' => new CanonicalOperationType('tenant.review_pack.generate', 'platform_foundation', 'review_pack', 'Review pack generation', true, 60), 'tenant.review.compose' => new CanonicalOperationType('tenant.review.compose', 'platform_foundation', 'tenant_review', 'Review composition', true, 60), 'tenant.evidence.snapshot.generate' => new CanonicalOperationType('tenant.evidence.snapshot.generate', 'platform_foundation', 'evidence_snapshot', 'Evidence snapshot generation', true, 120), 'rbac.health_check' => new CanonicalOperationType('rbac.health_check', 'intune', null, 'RBAC health check', false, 30), 'findings.lifecycle.backfill' => new CanonicalOperationType('findings.lifecycle.backfill', 'platform_foundation', null, 'Findings lifecycle backfill', false, 300), ]; } /** * @return list */ private static function operationAliases(): array { return [ new OperationTypeAlias('policy.sync', 'policy.sync', 'canonical', true), new OperationTypeAlias('policy.sync_one', 'policy.sync', 'legacy_alias', true, 'Legacy single-policy sync values resolve to the canonical policy.sync operation.', 'Prefer policy.sync on platform-owned read paths.'), new OperationTypeAlias('policy.capture_snapshot', 'policy.snapshot', 'canonical', true), new OperationTypeAlias('policy.delete', 'policy.delete', 'canonical', true), new OperationTypeAlias('policy.unignore', 'policy.restore', 'legacy_alias', true, 'Legacy policy.unignore values resolve to policy.restore for operator-facing wording.', 'Prefer policy.restore on new platform-owned read models.'), new OperationTypeAlias('policy.export', 'policy.export', 'canonical', true), new OperationTypeAlias('provider.connection.check', 'provider.connection.check', 'canonical', true), new OperationTypeAlias('inventory_sync', 'inventory.sync', 'legacy_alias', true, 'Legacy inventory_sync storage values resolve to the canonical inventory.sync operation.', 'Preserve stored values during rollout while showing inventory.sync semantics on read paths.'), new OperationTypeAlias('provider.inventory.sync', 'inventory.sync', 'legacy_alias', false, 'Provider-prefixed historical inventory sync values share the same operator meaning as inventory sync.', 'Avoid emitting provider.inventory.sync on new platform-owned surfaces.'), new OperationTypeAlias('compliance.snapshot', 'compliance.snapshot', 'canonical', true), new OperationTypeAlias('provider.compliance.snapshot', 'compliance.snapshot', 'legacy_alias', false, 'Provider-prefixed compliance snapshot values resolve to the canonical compliance.snapshot operation.', 'Avoid emitting provider.compliance.snapshot on new platform-owned surfaces.'), new OperationTypeAlias('entra_group_sync', 'directory.groups.sync', 'legacy_alias', true, 'Historical entra_group_sync values resolve to directory.groups.sync.', 'Prefer directory.groups.sync on new platform-owned read models.'), new OperationTypeAlias('backup_set.add_policies', 'backup_set.update', 'canonical', true), new OperationTypeAlias('backup_set.remove_policies', 'backup_set.update', 'legacy_alias', true, 'Removal and addition both resolve to the same backup-set update operator meaning.', 'Use backup_set.update for canonical reporting buckets.'), new OperationTypeAlias('backup_set.delete', 'backup_set.archive', 'canonical', true), new OperationTypeAlias('backup_set.restore', 'backup_set.restore', 'canonical', true), new OperationTypeAlias('backup_set.force_delete', 'backup_set.delete', 'legacy_alias', true, 'Force-delete wording is normalized to the canonical delete label.', 'Use backup_set.delete for new platform-owned summaries.'), new OperationTypeAlias('backup_schedule_run', 'backup.schedule.execute', 'legacy_alias', true, 'Historical backup_schedule_run values resolve to backup.schedule.execute.', 'Prefer backup.schedule.execute on canonical read paths.'), new OperationTypeAlias('backup_schedule_retention', 'backup.schedule.retention', 'legacy_alias', true, 'Legacy backup schedule retention values resolve to backup.schedule.retention.', 'Prefer dotted canonical backup schedule naming on new read paths.'), new OperationTypeAlias('backup_schedule_purge', 'backup.schedule.purge', 'legacy_alias', true, 'Legacy backup schedule purge values resolve to backup.schedule.purge.', 'Prefer dotted canonical backup schedule naming on new read paths.'), new OperationTypeAlias('restore.execute', 'restore.execute', 'canonical', true), new OperationTypeAlias('assignments.fetch', 'assignments.fetch', 'canonical', true), new OperationTypeAlias('assignments.restore', 'assignments.restore', 'canonical', true), new OperationTypeAlias('ops.reconcile_adapter_runs', 'ops.reconcile_adapter_runs', 'canonical', true), new OperationTypeAlias('directory_role_definitions.sync', 'directory.role_definitions.sync', 'legacy_alias', true, 'Legacy directory_role_definitions.sync values resolve to directory.role_definitions.sync.', 'Prefer dotted role-definition naming on new read paths.'), new OperationTypeAlias('restore_run.delete', 'restore_run.delete', 'canonical', true), new OperationTypeAlias('restore_run.restore', 'restore_run.restore', 'canonical', true), new OperationTypeAlias('restore_run.force_delete', 'restore_run.force_delete', 'canonical', true), new OperationTypeAlias('tenant.sync', 'tenant.sync', 'canonical', true), new OperationTypeAlias('policy_version.prune', 'policy_version.prune', 'canonical', true), new OperationTypeAlias('policy_version.restore', 'policy_version.restore', 'canonical', true), new OperationTypeAlias('policy_version.force_delete', 'policy_version.force_delete', 'canonical', true), new OperationTypeAlias('alerts.evaluate', 'alerts.evaluate', 'canonical', true), new OperationTypeAlias('alerts.deliver', 'alerts.deliver', 'canonical', true), new OperationTypeAlias('baseline_capture', 'baseline.capture', 'legacy_alias', true, 'Historical baseline_capture values resolve to baseline.capture.', 'Prefer baseline.capture on canonical read paths.'), new OperationTypeAlias('baseline_compare', 'baseline.compare', 'legacy_alias', true, 'Historical baseline_compare values resolve to baseline.compare.', 'Prefer baseline.compare on canonical read paths.'), new OperationTypeAlias('permission_posture_check', 'permission.posture.check', 'legacy_alias', true, 'Historical permission_posture_check values resolve to permission.posture.check.', 'Prefer dotted permission posture naming on new read paths.'), new OperationTypeAlias('entra.admin_roles.scan', 'entra.admin_roles.scan', 'canonical', true), new OperationTypeAlias('tenant.review_pack.generate', 'tenant.review_pack.generate', 'canonical', true), new OperationTypeAlias('tenant.review.compose', 'tenant.review.compose', 'canonical', true), new OperationTypeAlias('tenant.evidence.snapshot.generate', 'tenant.evidence.snapshot.generate', 'canonical', true), new OperationTypeAlias('rbac.health_check', 'rbac.health_check', 'canonical', true), new OperationTypeAlias('findings.lifecycle.backfill', 'findings.lifecycle.backfill', 'canonical', true), ]; } }