*/ public function detailEntries(string $sourceType, Model $record): array { return array_map( static fn (RelatedContextEntry $entry): array => $entry->toArray(), $this->resolveEntries($sourceType, CrossResourceNavigationMatrix::SURFACE_DETAIL_SECTION, $record), ); } public function primaryListAction(string $sourceType, Model $record): ?RelatedContextEntry { $entries = array_values(array_filter( $this->resolveEntries($sourceType, CrossResourceNavigationMatrix::SURFACE_LIST_ROW, $record), static fn (RelatedContextEntry $entry): bool => $entry->isAvailable(), )); return $entries[0] ?? null; } /** * @return array */ public function operationLinks(OperationRun $run, ?Tenant $tenant): array { $entries = array_filter( $this->resolveEntries(CrossResourceNavigationMatrix::SOURCE_OPERATION_RUN, CrossResourceNavigationMatrix::SURFACE_DETAIL_SECTION, $run), static fn (RelatedContextEntry $entry): bool => $entry->isAvailable(), ); $links = []; foreach ($entries as $entry) { $links[$entry->actionLabel] = (string) $entry->targetUrl; } if ($tenant instanceof Tenant) { $links = ['Open operations' => OperationRunLinks::index($tenant)] + $links; } else { $links = ['Open operations' => OperationRunLinks::index()] + $links; } return $links; } /** * @return list */ public function headerEntries(string $sourceType, Model $record): array { return $this->resolveEntries($sourceType, CrossResourceNavigationMatrix::SURFACE_DETAIL_HEADER, $record); } /** * @return list */ private function resolveEntries(string $sourceType, string $surface, Model $record): array { $entries = []; foreach ($this->matrix->rulesFor($sourceType, $surface) as $rule) { $entry = $this->resolveRule($rule, $record); if ($entry instanceof RelatedContextEntry) { $entries[] = $entry; } } usort( $entries, static fn (RelatedContextEntry $left, RelatedContextEntry $right): int => $left->priority <=> $right->priority, ); return $entries; } private function resolveRule(NavigationMatrixRule $rule, Model $record): ?RelatedContextEntry { return match ($rule->sourceType) { CrossResourceNavigationMatrix::SOURCE_FINDING => $record instanceof Finding ? $this->resolveFindingRule($rule, $record) : null, CrossResourceNavigationMatrix::SOURCE_POLICY_VERSION => $record instanceof PolicyVersion ? $this->resolvePolicyVersionRule($rule, $record) : null, CrossResourceNavigationMatrix::SOURCE_BASELINE_SNAPSHOT => $record instanceof BaselineSnapshot ? $this->resolveBaselineSnapshotRule($rule, $record) : null, CrossResourceNavigationMatrix::SOURCE_BACKUP_SET => $record instanceof BackupSet ? $this->resolveBackupSetRule($rule, $record) : null, CrossResourceNavigationMatrix::SOURCE_OPERATION_RUN => $record instanceof OperationRun ? $this->resolveOperationRunRule($rule, $record) : null, CrossResourceNavigationMatrix::SOURCE_BASELINE_PROFILE => $record instanceof BaselineProfile ? $this->resolveBaselineProfileRule($rule, $record) : null, default => null, }; } private function resolveFindingRule(NavigationMatrixRule $rule, Finding $finding): ?RelatedContextEntry { return match ($rule->relationKey) { 'baseline_snapshot' => $this->baselineSnapshotEntry( rule: $rule, snapshotId: $this->findingSnapshotId($finding), workspaceId: (int) $finding->workspace_id, ), 'source_run' => $this->operationRunEntry( rule: $rule, runId: $this->findingRunId($finding), workspaceId: (int) $finding->workspace_id, context: $this->contextForFinding($finding, $rule->sourceSurface), ), 'current_policy_version' => $this->policyVersionEntry( rule: $rule, policyVersionId: $this->findingPolicyVersionId($finding), tenantId: (int) $finding->tenant_id, ), 'parent_policy' => $this->parentPolicyEntryForFinding($rule, $finding), 'baseline_profile' => $this->baselineProfileEntry( rule: $rule, profileId: $this->findingProfileId($finding), workspaceId: (int) $finding->workspace_id, ), default => null, }; } private function resolvePolicyVersionRule(NavigationMatrixRule $rule, PolicyVersion $version): ?RelatedContextEntry { return match ($rule->relationKey) { 'parent_policy' => $this->policyEntry( rule: $rule, policy: $version->policy, ), 'baseline_snapshot' => $this->policyVersionSnapshotEntry($rule, $version), 'baseline_profile' => $this->baselineProfileEntry( rule: $rule, profileId: is_numeric($version->baseline_profile_id ?? null) ? (int) $version->baseline_profile_id : null, workspaceId: (int) $version->workspace_id, ), 'source_run' => $this->operationRunEntry( rule: $rule, runId: is_numeric($version->operation_run_id ?? null) ? (int) $version->operation_run_id : null, workspaceId: (int) $version->workspace_id, context: $this->contextForPolicyVersion($version, $rule->sourceSurface), ), default => null, }; } private function resolveBaselineSnapshotRule(NavigationMatrixRule $rule, BaselineSnapshot $snapshot): ?RelatedContextEntry { return match ($rule->relationKey) { 'baseline_profile' => $this->policyProfileEntry( rule: $rule, profile: $snapshot->baselineProfile, ), 'source_run' => $this->snapshotRunEntry($rule, $snapshot), 'policy_version' => $this->snapshotPolicyVersionEntry($rule, $snapshot), default => null, }; } private function resolveBackupSetRule(NavigationMatrixRule $rule, BackupSet $backupSet): ?RelatedContextEntry { return match ($rule->relationKey) { 'source_run' => $this->backupSetRunEntry($rule, $backupSet), 'operations' => $this->operationsEntry( rule: $rule, tenant: $backupSet->tenant, context: $this->contextForBackupSet($backupSet, $rule->sourceSurface), ), default => null, }; } private function resolveOperationRunRule(NavigationMatrixRule $rule, OperationRun $run): ?RelatedContextEntry { $context = is_array($run->context) ? $run->context : []; return match ($rule->relationKey) { 'backup_set' => $this->backupSetEntry( rule: $rule, backupSetId: is_numeric($context['backup_set_id'] ?? null) ? (int) $context['backup_set_id'] : null, tenantId: is_numeric($run->tenant_id ?? null) ? (int) $run->tenant_id : null, ), 'restore_run' => $this->restoreRunEntry( rule: $rule, restoreRunId: is_numeric($context['restore_run_id'] ?? null) ? (int) $context['restore_run_id'] : null, tenantId: is_numeric($run->tenant_id ?? null) ? (int) $run->tenant_id : null, ), 'baseline_profile' => $this->baselineProfileEntry( rule: $rule, profileId: is_numeric($context['baseline_profile_id'] ?? null) ? (int) $context['baseline_profile_id'] : null, workspaceId: (int) $run->workspace_id, ), 'baseline_snapshot' => $this->baselineSnapshotEntry( rule: $rule, snapshotId: is_numeric($context['baseline_snapshot_id'] ?? null) ? (int) $context['baseline_snapshot_id'] : null, workspaceId: (int) $run->workspace_id, ), 'parent_policy' => $this->operationRunPolicyEntry($rule, $run), 'operations' => $this->operationsEntry( rule: $rule, tenant: $run->tenant, context: $this->contextForOperationRun($run), ), default => null, }; } private function resolveBaselineProfileRule(NavigationMatrixRule $rule, BaselineProfile $profile): ?RelatedContextEntry { return match ($rule->relationKey) { 'baseline_snapshot' => $this->baselineSnapshotEntry( rule: $rule, snapshotId: is_numeric($profile->active_snapshot_id ?? null) ? (int) $profile->active_snapshot_id : null, workspaceId: (int) $profile->workspace_id, ), default => null, }; } private function findingSnapshotId(Finding $finding): ?int { $snapshotId = Arr::get($finding->evidence_jsonb ?? [], 'provenance.baseline_snapshot_id'); if (! is_numeric($snapshotId)) { $snapshotId = Arr::get($finding->evidence_jsonb ?? [], 'baseline_snapshot_id'); } return is_numeric($snapshotId) ? (int) $snapshotId : null; } private function findingProfileId(Finding $finding): ?int { $profileId = Arr::get($finding->evidence_jsonb ?? [], 'provenance.baseline_profile_id'); return is_numeric($profileId) ? (int) $profileId : null; } private function findingPolicyVersionId(Finding $finding): ?int { $policyVersionId = Arr::get($finding->evidence_jsonb ?? [], 'current.policy_version_id'); if (! is_numeric($policyVersionId)) { $policyVersionId = Arr::get($finding->evidence_jsonb ?? [], 'baseline.policy_version_id'); } return is_numeric($policyVersionId) ? (int) $policyVersionId : null; } private function findingRunId(Finding $finding): ?int { $runId = Arr::get($finding->evidence_jsonb ?? [], 'provenance.compare_operation_run_id'); if (is_numeric($runId)) { return (int) $runId; } if (is_numeric($finding->current_operation_run_id ?? null)) { return (int) $finding->current_operation_run_id; } return is_numeric($finding->baseline_operation_run_id ?? null) ? (int) $finding->baseline_operation_run_id : null; } private function policyVersionSnapshotEntry(NavigationMatrixRule $rule, PolicyVersion $version): ?RelatedContextEntry { $snapshotItem = BaselineSnapshotItem::query() ->where('meta_jsonb->version_reference->policy_version_id', (int) $version->getKey()) ->whereHas('snapshot', fn ($query) => $query->where('workspace_id', (int) $version->workspace_id)) ->with('snapshot.baselineProfile') ->latest('id') ->first(); if (! $snapshotItem instanceof BaselineSnapshotItem) { return null; } $snapshot = $snapshotItem->snapshot; return $snapshot instanceof BaselineSnapshot ? $this->baselineSnapshotEntry($rule, (int) $snapshot->getKey(), (int) $version->workspace_id) : null; } private function snapshotRunEntry(NavigationMatrixRule $rule, BaselineSnapshot $snapshot): ?RelatedContextEntry { $candidate = OperationRun::query() ->where('workspace_id', (int) $snapshot->workspace_id) ->where('context->baseline_snapshot_id', (int) $snapshot->getKey()) ->orderByDesc('completed_at') ->orderByDesc('id') ->first(); return $candidate instanceof OperationRun ? $this->operationRunEntry( rule: $rule, runId: (int) $candidate->getKey(), workspaceId: (int) $snapshot->workspace_id, context: $this->contextForBaselineSnapshot($snapshot, $rule->sourceSurface), ) : null; } private function snapshotPolicyVersionEntry(NavigationMatrixRule $rule, BaselineSnapshot $snapshot): ?RelatedContextEntry { $snapshotItem = BaselineSnapshotItem::query() ->where('baseline_snapshot_id', (int) $snapshot->getKey()) ->whereNotNull('meta_jsonb->version_reference->policy_version_id') ->orderBy('id') ->first(); if (! $snapshotItem instanceof BaselineSnapshotItem) { return null; } $policyVersionId = data_get($snapshotItem->meta_jsonb, 'version_reference.policy_version_id'); return $this->policyVersionEntry( rule: $rule, policyVersionId: is_numeric($policyVersionId) ? (int) $policyVersionId : null, tenantId: $this->activeTenantId(), ); } private function backupSetRunEntry(NavigationMatrixRule $rule, BackupSet $backupSet): ?RelatedContextEntry { $candidate = OperationRun::query() ->where('tenant_id', (int) $backupSet->tenant_id) ->where('context->backup_set_id', (int) $backupSet->getKey()) ->orderByDesc('completed_at') ->orderByDesc('id') ->first(); return $candidate instanceof OperationRun ? $this->operationRunEntry( rule: $rule, runId: (int) $candidate->getKey(), workspaceId: (int) $backupSet->workspace_id, context: $this->contextForBackupSet($backupSet, $rule->sourceSurface), ) : null; } private function operationRunPolicyEntry(NavigationMatrixRule $rule, OperationRun $run): ?RelatedContextEntry { $policyId = data_get($run->context, 'policy_id'); if (! is_numeric($policyId)) { return null; } $policy = Policy::query() ->whereKey((int) $policyId) ->where('tenant_id', (int) $run->tenant_id) ->first(); return $this->policyEntry($rule, $policy); } private function parentPolicyEntryForFinding(NavigationMatrixRule $rule, Finding $finding): ?RelatedContextEntry { $policyVersionId = $this->findingPolicyVersionId($finding); if ($policyVersionId === null) { return null; } $version = PolicyVersion::query() ->with('policy') ->whereKey($policyVersionId) ->where('tenant_id', (int) $finding->tenant_id) ->first(); if (! $version instanceof PolicyVersion) { return null; } return $this->policyEntry($rule, $version->policy); } private function baselineSnapshotEntry( NavigationMatrixRule $rule, ?int $snapshotId, int $workspaceId, ): ?RelatedContextEntry { if ($snapshotId === null || $snapshotId <= 0) { return null; } return $this->resolveReferenceEntry( rule: $rule, descriptor: new ReferenceDescriptor( referenceClass: ReferenceClass::BaselineSnapshot, rawIdentifier: (string) $snapshotId, workspaceId: $workspaceId, sourceType: $rule->sourceType, sourceSurface: $rule->sourceSurface, linkedModelId: $snapshotId, ), ); } private function baselineProfileEntry( NavigationMatrixRule $rule, ?int $profileId, int $workspaceId, ): ?RelatedContextEntry { if ($profileId === null || $profileId <= 0) { return null; } $profile = BaselineProfile::query() ->whereKey($profileId) ->where('workspace_id', $workspaceId) ->first(); if (! $profile instanceof BaselineProfile) { return $this->unavailableEntry($rule, (string) $profileId, 'missing'); } return $this->policyProfileEntry($rule, $profile); } private function policyProfileEntry(NavigationMatrixRule $rule, ?BaselineProfile $profile): ?RelatedContextEntry { if (! $profile instanceof BaselineProfile) { return null; } return $this->resolveReferenceEntry( rule: $rule, descriptor: new ReferenceDescriptor( referenceClass: ReferenceClass::BaselineProfile, rawIdentifier: (string) $profile->getKey(), workspaceId: (int) $profile->workspace_id, sourceType: $rule->sourceType, sourceSurface: $rule->sourceSurface, fallbackLabel: (string) $profile->name, linkedModelId: (int) $profile->getKey(), ), ); } private function operationRunEntry( NavigationMatrixRule $rule, ?int $runId, int $workspaceId, ?CanonicalNavigationContext $context = null, ): ?RelatedContextEntry { if ($runId === null || $runId <= 0) { return null; } return $this->resolveReferenceEntry( rule: $rule, descriptor: new ReferenceDescriptor( referenceClass: ReferenceClass::OperationRun, rawIdentifier: (string) $runId, workspaceId: $workspaceId, sourceType: $rule->sourceType, sourceSurface: $rule->sourceSurface, linkedModelId: $runId, context: [ 'navigation_context' => $context, ], ), ); } private function policyVersionEntry( NavigationMatrixRule $rule, ?int $policyVersionId, ?int $tenantId, ): ?RelatedContextEntry { if ($policyVersionId === null || $policyVersionId <= 0 || $tenantId === null || $tenantId <= 0) { return null; } return $this->resolveReferenceEntry( rule: $rule, descriptor: new ReferenceDescriptor( referenceClass: ReferenceClass::PolicyVersion, rawIdentifier: (string) $policyVersionId, tenantId: $tenantId, sourceType: $rule->sourceType, sourceSurface: $rule->sourceSurface, linkedModelId: $policyVersionId, ), ); } private function policyEntry(NavigationMatrixRule $rule, ?Policy $policy): ?RelatedContextEntry { if (! $policy instanceof Policy) { return null; } return $this->resolveReferenceEntry( rule: $rule, descriptor: new ReferenceDescriptor( referenceClass: ReferenceClass::Policy, rawIdentifier: (string) $policy->getKey(), tenantId: is_numeric($policy->tenant_id ?? null) ? (int) $policy->tenant_id : null, sourceType: $rule->sourceType, sourceSurface: $rule->sourceSurface, fallbackLabel: (string) ($policy->display_name ?: 'Policy'), linkedModelId: (int) $policy->getKey(), ), ); } private function backupSetEntry( NavigationMatrixRule $rule, ?int $backupSetId, ?int $tenantId, ): ?RelatedContextEntry { if ($backupSetId === null || $backupSetId <= 0 || $tenantId === null || $tenantId <= 0) { return null; } return $this->resolveReferenceEntry( rule: $rule, descriptor: new ReferenceDescriptor( referenceClass: ReferenceClass::BackupSet, rawIdentifier: (string) $backupSetId, tenantId: $tenantId, sourceType: $rule->sourceType, sourceSurface: $rule->sourceSurface, linkedModelId: $backupSetId, ), ); } private function resolveReferenceEntry(NavigationMatrixRule $rule, ReferenceDescriptor $descriptor): ?RelatedContextEntry { return $this->relatedContextReferenceAdapter->adapt( rule: $rule, reference: $this->referenceResolverRegistry->resolve($descriptor), ); } private function restoreRunEntry( NavigationMatrixRule $rule, ?int $restoreRunId, ?int $tenantId, ): ?RelatedContextEntry { if ($restoreRunId === null || $restoreRunId <= 0 || $tenantId === null || $tenantId <= 0) { return null; } $restoreRun = RestoreRun::query() ->with('tenant') ->whereKey($restoreRunId) ->where('tenant_id', $tenantId) ->first(); if (! $restoreRun instanceof RestoreRun) { return $this->unavailableEntry($rule, (string) $restoreRunId, 'missing'); } if (! $this->canOpenTenantRecord($restoreRun->tenant, Capabilities::TENANT_VIEW)) { return $this->unavailableEntry($rule, '#'.$restoreRunId, 'unauthorized'); } return RelatedContextEntry::available( key: $rule->relationKey, label: $this->labels->entryLabel($rule->relationKey), value: 'Restore run', secondaryValue: '#'.$restoreRun->getKey(), targetUrl: RestoreRunResource::getUrl('view', ['record' => $restoreRun], tenant: $restoreRun->tenant), targetKind: $rule->targetType, priority: $rule->priority, actionLabel: $this->labels->actionLabel($rule->relationKey), contextBadge: 'Tenant', ); } private function operationsEntry( NavigationMatrixRule $rule, ?Tenant $tenant, ?CanonicalNavigationContext $context = null, ): ?RelatedContextEntry { if (! $tenant instanceof Tenant) { return null; } if (! $this->canOpenTenantRecord($tenant, Capabilities::TENANT_VIEW)) { return null; } return RelatedContextEntry::available( key: $rule->relationKey, label: $this->labels->entryLabel($rule->relationKey), value: 'Operations', secondaryValue: $tenant->name, targetUrl: OperationRunLinks::index($tenant, $context), targetKind: $rule->targetType, priority: $rule->priority, actionLabel: $this->labels->actionLabel($rule->relationKey), contextBadge: 'Tenant context', ); } private function unavailableEntry(NavigationMatrixRule $rule, ?string $referenceValue, string $reason): ?RelatedContextEntry { if ($rule->missingStatePolicy === 'hide') { return null; } return RelatedContextEntry::unavailable( key: $rule->relationKey, label: $this->labels->entryLabel($rule->relationKey), state: new UnavailableRelationState( relationKey: $rule->relationKey, referenceValue: $referenceValue, reason: $reason, message: $this->labels->unavailableMessage($rule->relationKey, $reason), showReference: $rule->missingStatePolicy === 'show_reference_only', ), targetKind: $rule->targetType, priority: $rule->priority, actionLabel: $this->labels->actionLabel($rule->relationKey), ); } private function canOpenOperationRun(OperationRun $run): bool { $user = auth()->user(); return $user instanceof User && $user->can('view', $run); } private function canOpenWorkspaceBaselines(int $workspaceId): bool { $user = auth()->user(); if (! $user instanceof User) { return false; } $workspace = Workspace::query()->whereKey($workspaceId)->first(); if (! $workspace instanceof Workspace) { return false; } return $this->workspaceCapabilityResolver->isMember($user, $workspace) && $this->workspaceCapabilityResolver->can($user, $workspace, Capabilities::WORKSPACE_BASELINES_VIEW); } private function canOpenTenantRecord(?Tenant $tenant, string $capability): bool { $user = auth()->user(); return $tenant instanceof Tenant && $user instanceof User && $this->capabilityResolver->isMember($user, $tenant) && $this->capabilityResolver->can($user, $tenant, $capability); } private function canOpenPolicyVersion(PolicyVersion $version): bool { $tenant = $version->tenant; if (! $tenant instanceof Tenant || ! $this->canOpenTenantRecord($tenant, Capabilities::TENANT_VIEW)) { return false; } if (in_array((string) $version->capture_purpose?->value, ['baseline_capture', 'baseline_compare'], true)) { $user = auth()->user(); return $user instanceof User && $this->capabilityResolver->isMember($user, $tenant) && $this->capabilityResolver->can($user, $tenant, Capabilities::TENANT_SYNC); } return true; } private function canOpenPolicy(Policy $policy): bool { return $this->canOpenTenantRecord($policy->tenant, Capabilities::TENANT_VIEW); } private function contextForFinding(Finding $finding, string $surface): CanonicalNavigationContext { $tenant = $finding->tenant; $backLabel = $surface === CrossResourceNavigationMatrix::SURFACE_LIST_ROW ? 'Back to findings' : 'Back to finding'; $backUrl = $surface === CrossResourceNavigationMatrix::SURFACE_LIST_ROW ? FindingResource::getUrl('index', tenant: $tenant) : FindingResource::getUrl('view', ['record' => $finding], tenant: $tenant); return new CanonicalNavigationContext( sourceSurface: 'finding.'.$surface, canonicalRouteName: 'admin.operations.view', tenantId: $tenant?->getKey(), backLinkLabel: $backLabel, backLinkUrl: $backUrl, filterPayload: $tenant instanceof Tenant ? [ 'tableFilters' => [ 'tenant_id' => ['value' => (string) $tenant->getKey()], ], ] : [], ); } private function contextForPolicyVersion(PolicyVersion $version, string $surface): CanonicalNavigationContext { $tenant = $version->tenant; $backLabel = $surface === CrossResourceNavigationMatrix::SURFACE_LIST_ROW ? 'Back to policy versions' : 'Back to policy version'; $backUrl = $surface === CrossResourceNavigationMatrix::SURFACE_LIST_ROW ? PolicyVersionResource::getUrl('index', tenant: $tenant) : PolicyVersionResource::getUrl('view', ['record' => $version], tenant: $tenant); return new CanonicalNavigationContext( sourceSurface: 'policy_version.'.$surface, canonicalRouteName: 'admin.operations.view', tenantId: $tenant?->getKey(), backLinkLabel: $backLabel, backLinkUrl: $backUrl, filterPayload: $tenant instanceof Tenant ? [ 'tableFilters' => [ 'tenant_id' => ['value' => (string) $tenant->getKey()], ], ] : [], ); } private function contextForBaselineSnapshot(BaselineSnapshot $snapshot, string $surface): CanonicalNavigationContext { $backLabel = $surface === CrossResourceNavigationMatrix::SURFACE_LIST_ROW ? 'Back to baseline snapshots' : 'Back to baseline snapshot'; $backUrl = $surface === CrossResourceNavigationMatrix::SURFACE_LIST_ROW ? BaselineSnapshotResource::getUrl(panel: 'admin') : BaselineSnapshotResource::getUrl('view', ['record' => $snapshot], panel: 'admin'); return new CanonicalNavigationContext( sourceSurface: 'baseline_snapshot.'.$surface, canonicalRouteName: 'admin.operations.view', backLinkLabel: $backLabel, backLinkUrl: $backUrl, ); } private function contextForBackupSet(BackupSet $backupSet, string $surface): CanonicalNavigationContext { $tenant = $backupSet->tenant; $backLabel = $surface === CrossResourceNavigationMatrix::SURFACE_LIST_ROW ? 'Back to backup sets' : 'Back to backup set'; $backUrl = $surface === CrossResourceNavigationMatrix::SURFACE_LIST_ROW ? BackupSetResource::getUrl('index', tenant: $tenant) : BackupSetResource::getUrl('view', ['record' => $backupSet], tenant: $tenant); return new CanonicalNavigationContext( sourceSurface: 'backup_set.'.$surface, canonicalRouteName: 'admin.operations.view', tenantId: $tenant?->getKey(), backLinkLabel: $backLabel, backLinkUrl: $backUrl, filterPayload: $tenant instanceof Tenant ? [ 'tableFilters' => [ 'tenant_id' => ['value' => (string) $tenant->getKey()], ], ] : [], ); } private function contextForOperationRun(OperationRun $run): CanonicalNavigationContext { $tenant = $run->tenant; return new CanonicalNavigationContext( sourceSurface: 'operation_run.detail_section', canonicalRouteName: 'admin.operations.index', tenantId: $tenant?->getKey(), backLinkLabel: 'Back to operations', backLinkUrl: OperationRunLinks::index($tenant), filterPayload: $tenant instanceof Tenant ? [ 'tableFilters' => [ 'tenant_id' => ['value' => (string) $tenant->getKey()], ], ] : [], ); } private function activeTenantId(): ?int { $tenant = Filament::getTenant(); return $tenant instanceof Tenant ? (int) $tenant->getKey() : null; } }