IDs of policies synced or created */ public function syncPolicies(Tenant $tenant, ?array $supportedTypes = null): array { if (! $tenant->isActive()) { throw new \RuntimeException('Tenant is archived or inactive.'); } $types = $supportedTypes ?? config('tenantpilot.supported_policy_types', []); $synced = []; $tenantIdentifier = $tenant->tenant_id ?? $tenant->external_id; foreach ($types as $typeConfig) { $policyType = $typeConfig['type']; $platform = $typeConfig['platform'] ?? null; $this->graphLogger->logRequest('list_policies', [ 'tenant' => $tenantIdentifier, 'policy_type' => $policyType, 'platform' => $platform, ]); try { $response = $this->graphClient->listPolicies($policyType, [ 'tenant' => $tenantIdentifier, 'client_id' => $tenant->app_client_id, 'client_secret' => $tenant->app_client_secret, 'platform' => $platform, ]); } catch (Throwable $throwable) { throw GraphErrorMapper::fromThrowable($throwable, [ 'policy_type' => $policyType, 'tenant_id' => $tenant->id, 'tenant_identifier' => $tenantIdentifier, ]); } $this->graphLogger->logResponse('list_policies', $response, [ 'policy_type' => $policyType, 'tenant_id' => $tenant->id, 'tenant' => $tenantIdentifier, ]); if ($response->failed()) { continue; } foreach ($response->data as $policyData) { $externalId = $policyData['id'] ?? $policyData['external_id'] ?? null; if ($externalId === null) { continue; } $displayName = $policyData['displayName'] ?? $policyData['name'] ?? 'Unnamed policy'; $policyPlatform = $platform ?? ($policyData['platform'] ?? null); $policy = Policy::updateOrCreate( [ 'tenant_id' => $tenant->id, 'external_id' => $externalId, 'policy_type' => $policyType, ], [ 'display_name' => $displayName, 'platform' => $policyPlatform, 'last_synced_at' => now(), 'metadata' => Arr::except($policyData, ['id', 'external_id', 'displayName', 'name', 'platform']), ] ); $synced[] = $policy->id; } } return $synced; } }