feat: clean up legacy tenant environment context #372

Merged
ahmido merged 1 commits from 317-legacy-tenant-environment-context-cleanup into platform-dev 2026-05-16 18:25:38 +00:00
227 changed files with 2639 additions and 1193 deletions

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace App\Filament\Concerns;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
trait CleansAdminTenantQueryParameter
{
/**
* @param array<string, mixed> $parameters
*/
public static function getUrl(array $parameters = [], bool $isAbsolute = true, ?string $panel = null, ?Model $tenant = null): string
{
$panelId = $panel ?? Filament::getCurrentOrDefaultPanel()?->getId() ?? 'admin';
if ($panelId === 'admin') {
unset($parameters['tenant']);
return parent::getUrl($parameters, $isAbsolute, $panelId, null);
}
return parent::getUrl($parameters, $isAbsolute, $panelId, $tenant);
}
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace App\Filament\Concerns;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
trait CleansAdminTenantResourceQueryParameter
{
/**
* @param array<string, mixed> $parameters
*/
public static function getUrl(?string $name = null, array $parameters = [], bool $isAbsolute = true, ?string $panel = null, ?Model $tenant = null, bool $shouldGuessMissingParameters = false): string
{
$panelId = $panel ?? Filament::getCurrentOrDefaultPanel()?->getId() ?? 'admin';
if ($panelId === 'admin') {
unset($parameters['tenant']);
return parent::getUrl($name, $parameters, $isAbsolute, $panelId, null, $shouldGuessMissingParameters);
}
return parent::getUrl($name, $parameters, $isAbsolute, $panelId, $tenant, $shouldGuessMissingParameters);
}
}

View File

@ -0,0 +1,81 @@
<?php
declare(strict_types=1);
namespace App\Filament\Concerns;
use App\Models\ManagedEnvironment;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
trait UsesAdminEnvironmentFilterQueryParameter
{
/**
* @param array<string, mixed> $parameters
*/
public static function getUrl(array $parameters = [], bool $isAbsolute = true, ?string $panel = null, ?Model $tenant = null): string
{
$panelId = $panel ?? Filament::getCurrentOrDefaultPanel()?->getId() ?? 'admin';
if ($panelId !== 'admin') {
return parent::getUrl($parameters, $isAbsolute, $panelId, $tenant);
}
$environment = $tenant instanceof ManagedEnvironment ? $tenant : null;
$parameterTenant = $parameters['tenant'] ?? null;
if (! $environment instanceof ManagedEnvironment && $parameterTenant instanceof ManagedEnvironment) {
$environment = $parameterTenant;
}
unset($parameters['tenant']);
$url = parent::getUrl($parameters, $isAbsolute, $panelId, null);
return $environment instanceof ManagedEnvironment
? static::withEnvironmentId($url, $environment)
: $url;
}
private static function withEnvironmentId(string $url, ManagedEnvironment $environment): string
{
$parts = parse_url($url);
if (! is_array($parts)) {
return $url;
}
$query = [];
parse_str((string) ($parts['query'] ?? ''), $query);
$query['environment_id'] = (int) $environment->getKey();
unset($query['tenant'], $query['tenant_id'], $query['managed_environment_id'], $query['tenant_scope'], $query['environment']);
$parts['query'] = http_build_query($query, '', '&', PHP_QUERY_RFC3986);
$rebuilt = '';
if (isset($parts['scheme'])) {
$rebuilt .= $parts['scheme'].'://';
}
if (isset($parts['host'])) {
$rebuilt .= $parts['host'];
}
if (isset($parts['port'])) {
$rebuilt .= ':'.$parts['port'];
}
$rebuilt .= $parts['path'] ?? '';
if (($parts['query'] ?? '') !== '') {
$rebuilt .= '?'.$parts['query'];
}
if (isset($parts['fragment'])) {
$rebuilt .= '#'.$parts['fragment'];
}
return $rebuilt;
}
}

View File

@ -10,7 +10,7 @@
use Filament\Panel;
use Illuminate\Database\Eloquent\Model;
trait WorkspaceScopedTenantRoutes
trait WorkspaceScopedEnvironmentRoutes
{
public static function getSlug(?Panel $panel = null): string
{
@ -28,7 +28,7 @@ public static function getUrl(?string $name = null, array $parameters = [], bool
return parent::getUrl($name, $parameters, $isAbsolute, $panelId, $tenant, $shouldGuessMissingParameters);
}
$resolvedTenant = static::resolveWorkspaceScopedTenant($parameters, $tenant);
$resolvedTenant = static::resolveWorkspaceScopedEnvironment($parameters, $tenant);
if (! $resolvedTenant instanceof ManagedEnvironment) {
return url('/admin');
@ -49,7 +49,7 @@ public static function getUrl(?string $name = null, array $parameters = [], bool
protected static function workspaceScopedSlug(string $slug, ?Panel $panel = null): string
{
if (! static::shouldUseWorkspaceScopedTenantRoutes($panel)) {
if (! static::shouldUseWorkspaceScopedEnvironmentRoutes($panel)) {
return $slug;
}
@ -60,7 +60,7 @@ protected static function workspaceScopedSlug(string $slug, ?Panel $panel = null
: $prefix.ltrim($slug, '/');
}
protected static function shouldUseWorkspaceScopedTenantRoutes(?Panel $panel = null): bool
protected static function shouldUseWorkspaceScopedEnvironmentRoutes(?Panel $panel = null): bool
{
$panelId = $panel?->getId() ?? Filament::getCurrentOrDefaultPanel()?->getId() ?? 'admin';
@ -70,7 +70,7 @@ protected static function shouldUseWorkspaceScopedTenantRoutes(?Panel $panel = n
/**
* @param array<string, mixed> $parameters
*/
protected static function resolveWorkspaceScopedTenant(array $parameters, ?Model $tenant = null): ?ManagedEnvironment
protected static function resolveWorkspaceScopedEnvironment(array $parameters, ?Model $tenant = null): ?ManagedEnvironment
{
$parameterTenant = $parameters['tenant'] ?? $parameters['environment'] ?? null;
@ -85,7 +85,7 @@ protected static function resolveWorkspaceScopedTenant(array $parameters, ?Model
$record = $parameters['record'] ?? null;
if ($record instanceof Model) {
$relationshipName = static::workspaceScopedTenantRelationshipName();
$relationshipName = static::workspaceScopedEnvironmentRelationshipName();
if (method_exists($record, $relationshipName)) {
$recordTenant = $record->getRelationValue($relationshipName);
@ -139,7 +139,7 @@ protected static function resolveWorkspaceScopedWorkspace(ManagedEnvironment $te
return $tenant->workspace()->first();
}
protected static function workspaceScopedTenantRelationshipName(): string
protected static function workspaceScopedEnvironmentRelationshipName(): string
{
$relationshipName = property_exists(static::class, 'tenantOwnershipRelationshipName')
? static::$tenantOwnershipRelationshipName

View File

@ -5,11 +5,12 @@
namespace App\Filament\Pages;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\UsesAdminEnvironmentFilterQueryParameter;
use App\Filament\Resources\BaselineProfileResource;
use App\Filament\Resources\FindingResource;
use App\Models\BaselineProfile;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\User;
use App\Services\Auth\CapabilityResolver;
use App\Services\Baselines\BaselineCompareService;
@ -17,16 +18,16 @@
use App\Support\Baselines\BaselineCaptureMode;
use App\Support\Baselines\BaselineCompareEvidenceGapDetails;
use App\Support\Baselines\BaselineCompareStats;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\Navigation\NavigationScope;
use App\Support\Baselines\TenantGovernanceAggregate;
use App\Support\Baselines\TenantGovernanceAggregateResolver;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\Navigation\NavigationScope;
use App\Support\OperationRunLinks;
use App\Support\OperationRunType;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\OpsUx\OpsUxBrowserEvents;
use App\Support\ReasonTranslation\ReasonPresenter;
use App\Support\Rbac\UiEnforcement;
use App\Support\ReasonTranslation\ReasonPresenter;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
@ -39,6 +40,7 @@
class BaselineCompareLanding extends Page
{
use ResolvesPanelTenantContext;
use UsesAdminEnvironmentFilterQueryParameter;
protected const MONITORING_PAGE_STATE_CONTRACT = [
'surfaceKey' => 'baseline_compare_landing',

View File

@ -126,7 +126,7 @@ public function selectEnvironment(int $tenantId): void
$this->persistLastTenant($user, $tenant);
if (! $workspaceContext->rememberTenantContext($tenant, request())) {
if (! $workspaceContext->rememberEnvironmentContext($tenant, request())) {
abort(404);
}

View File

@ -12,7 +12,7 @@
use App\Models\Workspace;
use App\Services\Auth\WorkspaceCapabilityResolver;
use App\Services\Findings\FindingAssignmentHygieneService;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\Filament\TablePaginationProfiles;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\OperateHub\OperateHubShell;
@ -78,7 +78,7 @@ public function mount(): void
$this->reasonFilter = $this->resolveRequestedReasonFilter();
$this->authorizePageAccess();
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
[],
request(),
@ -486,14 +486,14 @@ private function filteredTenant(): ?ManagedEnvironment
private function activeVisibleTenant(): ?ManagedEnvironment
{
$activeTenant = app(OperateHubShell::class)->activeEntitledTenant(request());
$activeEnvironment = app(OperateHubShell::class)->activeEntitledTenant(request());
if (! $activeTenant instanceof ManagedEnvironment) {
if (! $activeEnvironment instanceof ManagedEnvironment) {
return null;
}
foreach ($this->visibleTenants() as $tenant) {
if ($tenant->is($activeTenant)) {
if ($tenant->is($activeEnvironment)) {
return $tenant;
}
}
@ -509,9 +509,9 @@ private function tenantPrefilterSource(): string
return 'none';
}
$activeTenant = $this->activeVisibleTenant();
$activeEnvironment = $this->activeVisibleTenant();
if ($activeTenant instanceof ManagedEnvironment && $activeTenant->is($tenant)) {
if ($activeEnvironment instanceof ManagedEnvironment && $activeEnvironment->is($tenant)) {
return 'active_tenant_context';
}

View File

@ -16,7 +16,7 @@
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\Filament\TablePaginationProfiles;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\OperateHub\OperateHubShell;
@ -92,7 +92,7 @@ public function mount(): void
$this->queueView = $this->resolveRequestedQueueView();
$this->authorizePageAccess();
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
[],
request(),
@ -494,12 +494,12 @@ private function filteredQueueQuery(
return $query
->orderByRaw(
"case
'case
when due_at is not null and due_at < ? then 0
when status = ? then 1
when status = ? then 2
else 3
end asc",
end asc',
[now(), Finding::STATUS_REOPENED, Finding::STATUS_NEW],
)
->orderByRaw('case when due_at is null then 1 else 0 end asc')
@ -605,14 +605,14 @@ private function filteredTenant(): ?ManagedEnvironment
private function activeVisibleTenant(): ?ManagedEnvironment
{
$activeTenant = app(OperateHubShell::class)->activeEntitledTenant(request());
$activeEnvironment = app(OperateHubShell::class)->activeEntitledTenant(request());
if (! $activeTenant instanceof ManagedEnvironment) {
if (! $activeEnvironment instanceof ManagedEnvironment) {
return null;
}
foreach ($this->visibleTenants() as $tenant) {
if ($tenant->is($activeTenant)) {
if ($tenant->is($activeEnvironment)) {
return $tenant;
}
}
@ -628,9 +628,9 @@ private function tenantPrefilterSource(): string
return 'none';
}
$activeTenant = $this->activeVisibleTenant();
$activeEnvironment = $this->activeVisibleTenant();
if ($activeTenant instanceof ManagedEnvironment && $activeTenant->is($tenant)) {
if ($activeEnvironment instanceof ManagedEnvironment && $activeEnvironment->is($tenant)) {
return 'active_tenant_context';
}

View File

@ -15,7 +15,7 @@
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\Filament\TablePaginationProfiles;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\OperateHub\OperateHubShell;
@ -84,7 +84,7 @@ public function mount(): void
{
$this->authorizePageAccess();
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
['overdue', 'reopened', 'high_severity'],
request(),
@ -270,9 +270,9 @@ public function emptyState(): array
];
}
$activeTenant = $this->activeVisibleTenant();
$activeEnvironment = $this->activeVisibleTenant();
if ($activeTenant instanceof ManagedEnvironment) {
if ($activeEnvironment instanceof ManagedEnvironment) {
return [
'title' => 'No visible assigned findings right now',
'body' => 'Nothing currently assigned to you needs attention in the visible environment scope. You can still open environment findings for broader context.',
@ -280,7 +280,7 @@ public function emptyState(): array
'action_name' => 'open_tenant_findings_empty',
'action_label' => 'Open environment findings',
'action_kind' => 'url',
'action_url' => FindingResource::getUrl('index', tenant: $activeTenant),
'action_url' => FindingResource::getUrl('index', tenant: $activeEnvironment),
];
}
@ -561,14 +561,14 @@ private function filteredTenant(): ?ManagedEnvironment
private function activeVisibleTenant(): ?ManagedEnvironment
{
$activeTenant = app(OperateHubShell::class)->activeEntitledTenant(request());
$activeEnvironment = app(OperateHubShell::class)->activeEntitledTenant(request());
if (! $activeTenant instanceof ManagedEnvironment) {
if (! $activeEnvironment instanceof ManagedEnvironment) {
return null;
}
foreach ($this->visibleTenants() as $tenant) {
if ($tenant->is($activeTenant)) {
if ($tenant->is($activeEnvironment)) {
return $tenant;
}
}
@ -584,9 +584,9 @@ private function tenantPrefilterSource(): string
return 'none';
}
$activeTenant = $this->activeVisibleTenant();
$activeEnvironment = $this->activeVisibleTenant();
if ($activeTenant instanceof ManagedEnvironment && $activeTenant->is($tenant)) {
if ($activeEnvironment instanceof ManagedEnvironment && $activeEnvironment->is($tenant)) {
return 'active_tenant_context';
}

View File

@ -4,6 +4,7 @@
namespace App\Filament\Pages\Governance;
use App\Filament\Concerns\CleansAdminTenantQueryParameter;
use App\Filament\Concerns\ClearsWorkspaceHubEnvironmentFilterState;
use App\Filament\Resources\FindingExceptionResource;
use App\Models\FindingException;
@ -40,6 +41,7 @@
class DecisionRegister extends Page implements HasTable
{
use CleansAdminTenantQueryParameter;
use ClearsWorkspaceHubEnvironmentFilterState;
use InteractsWithTable;

View File

@ -4,6 +4,7 @@
namespace App\Filament\Pages\Governance;
use App\Filament\Concerns\CleansAdminTenantQueryParameter;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
@ -29,6 +30,8 @@
class GovernanceInbox extends Page
{
use CleansAdminTenantQueryParameter;
protected static bool $isDiscovered = false;
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-inbox-stack';

View File

@ -5,8 +5,8 @@
namespace App\Filament\Pages\Monitoring;
use App\Models\AuditLog as AuditLogModel;
use App\Models\SupportAccessGrant;
use App\Models\ManagedEnvironment;
use App\Models\SupportAccessGrant;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Auth\WorkspaceCapabilityResolver;
@ -14,7 +14,7 @@
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\Filament\FilterOptionCatalog;
use App\Support\Filament\FilterPresets;
use App\Support\Filament\TablePaginationProfiles;
@ -164,7 +164,7 @@ public function mount(): void
$this->supportAccessOnly = request()->boolean('supportAccess');
$requestedEventId = is_numeric(request()->query('event')) ? (int) request()->query('event') : null;
app(CanonicalAdminTenantFilterState::class)->sync($this->getTableFiltersSessionKey(), request: request());
app(CanonicalAdminEnvironmentFilterState::class)->sync($this->getTableFiltersSessionKey(), request: request());
$this->mountInteractsWithTable();
@ -616,14 +616,14 @@ private function tenantFilterOptions(): array
private function defaultTenantFilter(): ?string
{
$activeTenant = app(OperateHubShell::class)->activeEntitledTenant(request());
$activeEnvironment = app(OperateHubShell::class)->activeEntitledTenant(request());
if (! $activeTenant instanceof ManagedEnvironment) {
if (! $activeEnvironment instanceof ManagedEnvironment) {
return null;
}
return array_key_exists((int) $activeTenant->getKey(), $this->authorizedTenants())
? (string) $activeTenant->getKey()
return array_key_exists((int) $activeEnvironment->getKey(), $this->authorizedTenants())
? (string) $activeEnvironment->getKey()
: null;
}

View File

@ -4,6 +4,7 @@
namespace App\Filament\Pages\Monitoring;
use App\Filament\Concerns\CleansAdminTenantQueryParameter;
use App\Filament\Concerns\ClearsWorkspaceHubEnvironmentFilterState;
use App\Filament\Resources\FindingExceptionResource;
use App\Filament\Resources\FindingResource;
@ -17,7 +18,7 @@
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\Filament\FilterOptionCatalog;
use App\Support\Filament\TablePaginationProfiles;
use App\Support\Navigation\CanonicalNavigationContext;
@ -52,6 +53,7 @@
class FindingExceptionsQueue extends Page implements HasTable
{
use CleansAdminTenantQueryParameter;
use ClearsWorkspaceHubEnvironmentFilterState;
use InteractsWithTable;
@ -653,7 +655,7 @@ private function filteredTenant(): ?ManagedEnvironment
private function currentTenantFilterId(): ?int
{
$tenantFilter = app(CanonicalAdminTenantFilterState::class)->currentFilterValue(
$tenantFilter = app(CanonicalAdminEnvironmentFilterState::class)->currentFilterValue(
$this->getTableFiltersSessionKey(),
$this->tableFilters ?? [],
request(),

View File

@ -13,7 +13,7 @@
use App\Models\Workspace;
use App\Services\Auth\ManagedEnvironmentAccessScopeResolver;
use App\Services\Auth\WorkspaceCapabilityResolver;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\Navigation\WorkspaceHubEnvironmentFilter;
@ -231,7 +231,7 @@ protected function getHeaderActions(): array
->disabled(),
];
$activeTenant = $this->currentTenantFilterId() === null
$activeEnvironment = $this->currentTenantFilterId() === null
? $operateHubShell->activeEntitledTenant(request())
: null;
@ -241,22 +241,22 @@ protected function getHeaderActions(): array
->icon('heroicon-o-arrow-left')
->color('gray')
->url($navigationContext->backLinkUrl);
} elseif ($activeTenant instanceof ManagedEnvironment) {
} elseif ($activeEnvironment instanceof ManagedEnvironment) {
$actions[] = Action::make('operate_hub_back_to_tenant_operations')
->label('Back to '.$activeTenant->name)
->label('Back to '.$activeEnvironment->name)
->icon('heroicon-o-arrow-left')
->color('gray')
->url(ManagedEnvironmentLinks::viewUrl($activeTenant));
->url(ManagedEnvironmentLinks::viewUrl($activeEnvironment));
}
if ($activeTenant instanceof ManagedEnvironment) {
if ($activeEnvironment instanceof ManagedEnvironment) {
$actions[] = Action::make('operate_hub_show_all_tenants')
->label(__('localization.shell.show_all_environments'))
->color('gray')
->action(function (): void {
Filament::setTenant(null, true);
app(WorkspaceContext::class)->clearLastTenantId(request());
app(WorkspaceContext::class)->clearLastEnvironmentId(request());
$this->removeTableFilter('managed_environment_id');
@ -283,7 +283,7 @@ public function landingHierarchySummary(): array
$operateHubShell = app(OperateHubShell::class);
$navigationContext = $this->navigationContext();
$filteredTenant = $this->filteredTenant();
$activeTenant = $filteredTenant instanceof ManagedEnvironment
$activeEnvironment = $filteredTenant instanceof ManagedEnvironment
? null
: $operateHubShell->activeEntitledTenant(request());
@ -293,8 +293,8 @@ public function landingHierarchySummary(): array
if ($navigationContext?->backLinkLabel !== null && $navigationContext->backLinkUrl !== null) {
$returnLabel = $navigationContext->backLinkLabel;
$returnBody = 'Return to the originating monitoring surface without competing with the current tab, filters, or row inspection flow.';
} elseif ($activeTenant instanceof ManagedEnvironment) {
$returnLabel = 'Back to '.$activeTenant->name;
} elseif ($activeEnvironment instanceof ManagedEnvironment) {
$returnLabel = 'Back to '.$activeEnvironment->name;
$returnBody = 'Return to the tenant dashboard when you need tenant-specific context outside this workspace monitoring landing.';
}
@ -302,13 +302,13 @@ public function landingHierarchySummary(): array
'scope_label' => $operateHubShell->scopeLabel(request()),
'scope_body' => $filteredTenant instanceof ManagedEnvironment
? 'The landing is workspace-scoped and filtered by an explicit environment filter.'
: ($activeTenant instanceof ManagedEnvironment
: ($activeEnvironment instanceof ManagedEnvironment
? 'The landing is currently narrowed to one environment inside the active workspace.'
: 'The landing is currently showing workspace-wide monitoring across all entitled environments.'),
'return_label' => $returnLabel,
'return_body' => $returnBody,
'scope_reset_label' => $activeTenant instanceof ManagedEnvironment ? __('localization.shell.show_all_environments') : null,
'scope_reset_body' => $activeTenant instanceof ManagedEnvironment
'scope_reset_label' => $activeEnvironment instanceof ManagedEnvironment ? __('localization.shell.show_all_environments') : null,
'scope_reset_body' => $activeEnvironment instanceof ManagedEnvironment
? 'Reset the landing back to workspace-wide monitoring when environment-specific context is no longer needed.'
: null,
'inspect_body' => 'Open a run from the table to enter the canonical monitoring detail viewer.',
@ -534,7 +534,7 @@ private function operationsUrl(array $overrides = []): string
private function currentTenantFilterId(): ?int
{
$tenantFilter = app(CanonicalAdminTenantFilterState::class)->currentFilterValue(
$tenantFilter = app(CanonicalAdminEnvironmentFilterState::class)->currentFilterValue(
$this->getTableFiltersSessionKey(),
$this->tableFilters ?? [],
request(),

View File

@ -5,9 +5,9 @@
namespace App\Filament\Pages\Operations;
use App\Filament\Resources\OperationRunResource;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\SupportRequest;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Services\Audit\WorkspaceAuditLogger;
use App\Services\Auth\CapabilityResolver;
@ -27,10 +27,10 @@
use App\Support\OpsUx\RunDetailPolling;
use App\Support\ProductTelemetry\ProductTelemetryRecorder;
use App\Support\ProductTelemetry\ProductUsageEventCatalog;
use App\Support\Rbac\UiEnforcement;
use App\Support\ReasonTranslation\ReasonPresenter;
use App\Support\RedactionIntegrity;
use App\Support\RestoreSafety\RestoreSafetyCopy;
use App\Support\Rbac\UiEnforcement;
use App\Support\SupportDiagnostics\SupportDiagnosticBundleBuilder;
use App\Support\SupportRequests\ExternalSupportDeskHandoffService;
use App\Support\SupportRequests\SupportRequestSubmissionService;
@ -46,15 +46,15 @@
use Filament\Actions\ActionGroup;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\EmbeddedSchema;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Schema;
use Illuminate\Contracts\View\View;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Str;
@ -108,7 +108,7 @@ protected function getHeaderActions(): array
{
$operateHubShell = app(OperateHubShell::class);
$navigationContext = $this->navigationContext();
$activeTenant = $operateHubShell->activeEntitledTenant(request());
$activeEnvironment = $operateHubShell->activeEntitledTenant(request());
$runTenantId = isset($this->run) ? (int) ($this->run->managed_environment_id ?? 0) : 0;
$actions = [
@ -123,11 +123,11 @@ protected function getHeaderActions(): array
->label($navigationContext->backLinkLabel)
->color('gray')
->url($navigationContext->backLinkUrl);
} elseif ($activeTenant instanceof ManagedEnvironment && (int) $activeTenant->getKey() === $runTenantId) {
} elseif ($activeEnvironment instanceof ManagedEnvironment && (int) $activeEnvironment->getKey() === $runTenantId) {
$actions[] = Action::make('operate_hub_back_to_tenant_run_detail')
->label('← Back to '.$activeTenant->name)
->label('← Back to '.$activeEnvironment->name)
->color('gray')
->url(ManagedEnvironmentLinks::viewUrl($activeTenant));
->url(ManagedEnvironmentLinks::viewUrl($activeEnvironment));
} else {
$actions[] = Action::make('operate_hub_back_to_operations')
->label('Back to Operations')
@ -135,7 +135,7 @@ protected function getHeaderActions(): array
->url(fn (): string => OperationRunLinks::index());
}
if ($activeTenant instanceof ManagedEnvironment) {
if ($activeEnvironment instanceof ManagedEnvironment) {
$actions[] = Action::make('operate_hub_show_all_operations')
->label('Show all operations')
->color('gray')
@ -201,7 +201,7 @@ public function monitoringDetailSummary(): array
{
$operateHubShell = app(OperateHubShell::class);
$navigationContext = $this->navigationContext();
$activeTenant = $operateHubShell->activeEntitledTenant(request());
$activeEnvironment = $operateHubShell->activeEntitledTenant(request());
$runTenantId = isset($this->run) ? (int) ($this->run->managed_environment_id ?? 0) : 0;
$navigationLabel = 'Back to Operations';
@ -210,8 +210,8 @@ public function monitoringDetailSummary(): array
if ($navigationContext?->backLinkLabel !== null && $navigationContext->backLinkUrl !== null) {
$navigationLabel = $navigationContext->backLinkLabel;
$navigationBody = 'Return to the originating surface while keeping refresh and follow-up work separate from navigation.';
} elseif ($activeTenant instanceof ManagedEnvironment && (int) $activeTenant->getKey() === $runTenantId) {
$navigationLabel = 'Back to '.$activeTenant->name;
} elseif ($activeEnvironment instanceof ManagedEnvironment && (int) $activeEnvironment->getKey() === $runTenantId) {
$navigationLabel = 'Back to '.$activeEnvironment->name;
$navigationBody = 'Return to the active tenant dashboard, then widen back to the workspace view only when you need broader monitoring context.';
}
@ -727,15 +727,15 @@ public function canonicalContextBanner(): ?array
return null;
}
$activeTenant = app(OperateHubShell::class)->activeEntitledTenant(request());
$activeEnvironment = app(OperateHubShell::class)->activeEntitledTenant(request());
$runTenant = $this->run->tenant;
if (! $runTenant instanceof ManagedEnvironment) {
return [
'tone' => 'slate',
'title' => 'Workspace-level operation',
'body' => $activeTenant instanceof ManagedEnvironment
? 'This canonical workspace view is not tied to the current environment context ('.$activeTenant->name.').'
'body' => $activeEnvironment instanceof ManagedEnvironment
? 'This canonical workspace view is not tied to the current environment context ('.$activeEnvironment->name.').'
: 'This canonical workspace view is not tied to any environment.',
];
}
@ -744,9 +744,9 @@ public function canonicalContextBanner(): ?array
$tone = 'sky';
$title = null;
if ($activeTenant instanceof ManagedEnvironment && ! $activeTenant->is($runTenant)) {
if ($activeEnvironment instanceof ManagedEnvironment && ! $activeEnvironment->is($runTenant)) {
$title = 'Current environment context differs from this operation';
array_unshift($messages, 'Current environment context: '.$activeTenant->name.'.');
array_unshift($messages, 'Current environment context: '.$activeEnvironment->name.'.');
$messages[] = 'This canonical workspace view remains valid without switching environment context.';
}
@ -760,7 +760,7 @@ public function canonicalContextBanner(): ?array
if ($referencedTenant->contextNote !== null) {
$messages[] = $referencedTenant->contextNote;
}
} elseif (! $activeTenant instanceof ManagedEnvironment) {
} elseif (! $activeEnvironment instanceof ManagedEnvironment) {
$title ??= 'Canonical workspace view';
$messages[] = 'No environment context is currently selected.';
}

View File

@ -4,6 +4,7 @@
namespace App\Filament\Pages\Reviews;
use App\Filament\Concerns\CleansAdminTenantQueryParameter;
use App\Filament\Concerns\ClearsWorkspaceHubEnvironmentFilterState;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\EnvironmentReview;
@ -50,6 +51,7 @@
class CustomerReviewWorkspace extends Page implements HasTable
{
use CleansAdminTenantQueryParameter;
use ClearsWorkspaceHubEnvironmentFilterState;
use InteractsWithTable;
@ -99,7 +101,7 @@ public function getTitle(): string
return __('localization.review.customer_review_workspace');
}
public static function tenantPrefilterUrl(ManagedEnvironment $tenant): string
public static function environmentFilterUrl(ManagedEnvironment $tenant): string
{
return static::getUrl(panel: 'admin').'?'.http_build_query([
'environment_id' => (int) $tenant->getKey(),
@ -573,7 +575,7 @@ private function latestReviewUrl(ManagedEnvironment $tenant): ?string
static fn (mixed $value): bool => $value !== null && $value !== '',
);
return $this->appendQuery(EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant), $query);
return $this->appendQuery(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant), $query);
}
private function reviewPackDownloadUrl(EnvironmentReview $review, ManagedEnvironment $tenant): ?string

View File

@ -4,6 +4,7 @@
namespace App\Filament\Pages\Reviews;
use App\Filament\Concerns\CleansAdminTenantQueryParameter;
use App\Filament\Concerns\ClearsWorkspaceHubEnvironmentFilterState;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\EnvironmentReview;
@ -45,6 +46,7 @@
class ReviewRegister extends Page implements HasTable
{
use CleansAdminTenantQueryParameter;
use ClearsWorkspaceHubEnvironmentFilterState;
use InteractsWithTable;
@ -111,7 +113,7 @@ public function table(Table $table): Table
->persistFiltersInSession()
->persistSearchInSession()
->persistSortInSession()
->recordUrl(fn (EnvironmentReview $record): string => EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $record], $record->tenant))
->recordUrl(fn (EnvironmentReview $record): string => EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $record], $record->tenant))
->columns([
TextColumn::make('tenant.name')->label('Environment')->searchable(),
TextColumn::make('status')

View File

@ -4,7 +4,6 @@
namespace App\Filament\Pages\Workspaces;
use BackedEnum;
use App\Exceptions\Onboarding\OnboardingDraftConflictException;
use App\Exceptions\Onboarding\OnboardingDraftImmutableException;
use App\Filament\Resources\ManagedEnvironmentResource;
@ -13,24 +12,22 @@
use App\Jobs\ProviderComplianceSnapshotJob;
use App\Jobs\ProviderConnectionHealthCheckJob;
use App\Jobs\ProviderInventorySyncJob;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\User;
use App\Models\VerificationCheckAcknowledgement;
use App\Models\Workspace;
use App\Services\Audit\WorkspaceAuditLogger;
use App\Services\Auth\ManagedEnvironmentMembershipManager;
use App\Services\Entitlements\WorkspaceCommercialLifecycleResolver;
use App\Services\Intune\AuditLogger;
use App\Services\Intune\ManagedEnvironmentRequiredPermissionsViewModelBuilder;
use App\Services\Onboarding\OnboardingDraftMutationService;
use App\Services\Onboarding\OnboardingDraftResolver;
use App\Services\Onboarding\OnboardingDraftStageResolver;
use App\Services\Onboarding\OnboardingLifecycleService;
use App\Services\Entitlements\WorkspaceCommercialLifecycleResolver;
use App\Services\Entitlements\WorkspaceEntitlementResolver;
use App\Services\OperationRunService;
use App\Services\Providers\ProviderConnectionMutationService;
use App\Services\Providers\ProviderOperationRegistry;
use App\Services\Providers\ProviderOperationStartGate;
@ -50,17 +47,16 @@
use App\Support\OperationRunLinks;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\OpsUx\ProviderOperationStartResultPresenter;
use App\Support\OpsUx\OpsUxBrowserEvents;
use App\Support\OpsUx\ProviderOperationStartResultPresenter;
use App\Support\ProductKnowledge\ContextualHelpResolver;
use App\Support\Providers\ProviderConnectionType;
use App\Support\Providers\ProviderConsentStatus;
use App\Support\Providers\ProviderReasonCodes;
use App\Support\Providers\ProviderVerificationStatus;
use App\Support\Providers\TargetScope\ProviderConnectionSurfaceSummary;
use App\Support\Providers\TargetScope\ProviderConnectionTargetScopeDescriptor;
use App\Support\Providers\TargetScope\ProviderConnectionTargetScopeNormalizer;
use App\Support\Providers\ProviderVerificationStatus;
use App\Support\Tenants\TenantInteractionLane;
use App\Support\Tenants\TenantLifecyclePresentation;
use App\Support\Tenants\TenantOperabilityQuestion;
@ -68,6 +64,7 @@
use App\Support\Verification\VerificationCheckStatus;
use App\Support\Verification\VerificationReportOverall;
use App\Support\Workspaces\WorkspaceContext;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\Radio;
@ -233,7 +230,7 @@ private function canViewLinkedEnvironment(): bool
return app(TenantOperabilityService::class)->outcomeFor(
tenant: $tenant,
question: TenantOperabilityQuestion::TenantBoundViewability,
question: TenantOperabilityQuestion::EnvironmentBoundViewability,
actor: $user,
workspaceId: (int) $this->workspace->getKey(),
lane: TenantInteractionLane::AdministrativeManagement,
@ -1108,7 +1105,7 @@ private function readinessSupportingEvidenceSchema(array $payload, string $keyPr
$actions[] = Action::make($keyPrefix.'_required_permissions_assist')
->label('View required permissions')
->color('gray')
->url($requiredPermissionsUrl);
->url($requiredPermissionsUrl);
}
if ($actions === []) {
@ -1206,7 +1203,7 @@ private function readinessPermissionDiagnosticsSchema(array $payload, string $ke
* draft: array{id: int, environment_name: string, stage_label: string, draft_status_label: string, started_by: string, updated_by: string, last_updated_human: string},
* checkpoint: array{current_checkpoint: string|null, current_checkpoint_label: string|null, last_completed_checkpoint: string|null, lifecycle_state: string, lifecycle_label: string},
* provider_summary: array<string, mixed>|null,
* verification: array{status: string, status_label: string, run_id: int|null, run_url: string|null, is_active: bool, has_report: bool, matches_selected_connection: bool|null, overall: string|null},
* verification: array{status: string, status_label: string, run_id: int|null, run_url: string|null, is_active: bool, has_report: bool, matches_selected_connection: bool|null, overall: string|null},
* verification_assist: array{is_visible: bool, reason: string},
* permissions: array{overall: string|null, counts: array<string, int>, freshness: array{last_refreshed_at: string|null, is_stale: bool}, capability_groups: array<int, array<string, mixed>>, primary_capability_group: array<string, mixed>|null, missing_permissions: array{application: list<string>, delegated: list<string>}, required_permissions_url: string|null}|null,
* freshness: array{connection_recently_updated: bool, verification_mismatch: bool, permission_last_refreshed_at: string|null, permission_data_is_stale: bool, note: string},
@ -4195,7 +4192,7 @@ public function startBootstrap(array $operationTypes): void
draft: $this->onboardingSession,
actor: $user,
expectedVersion: $this->expectedDraftVersion(),
mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($tenant, $connection, $types, $registry, $user, &$result): void {
mutator: function (ManagedEnvironmentOnboardingSession $draft) use ($tenant, $connection, $types, $user, &$result): void {
$nextOperationType = $this->nextBootstrapOperationType($draft, $types, (int) $connection->getKey());
if ($nextOperationType === null) {

View File

@ -5,7 +5,7 @@
namespace App\Filament\Resources\AlertDeliveryResource\Pages;
use App\Filament\Resources\AlertDeliveryResource;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\OperateHub\OperateHubShell;
use Filament\Actions\Action;
@ -17,7 +17,7 @@ class ListAlertDeliveries extends ListRecords
public function mount(): void
{
app(CanonicalAdminTenantFilterState::class)->sync($this->getTableFiltersSessionKey(), request: request());
app(CanonicalAdminEnvironmentFilterState::class)->sync($this->getTableFiltersSessionKey(), request: request());
parent::mount();
}

View File

@ -5,7 +5,7 @@
use App\Exceptions\InvalidPolicyTypeException;
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\BackupScheduleResource\Pages;
use App\Filament\Resources\BackupScheduleResource\RelationManagers\BackupScheduleOperationRunsRelationManager;
use App\Jobs\RunBackupScheduleJob;
@ -43,7 +43,6 @@
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\CreateAction;
use Filament\Facades\Filament;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
@ -70,7 +69,7 @@ class BackupScheduleResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = BackupSchedule::class;

View File

@ -3,11 +3,9 @@
namespace App\Filament\Resources\BackupScheduleResource\Pages;
use App\Filament\Resources\BackupScheduleResource;
use App\Models\ManagedEnvironment;
use App\Support\BackupHealth\TenantBackupHealthAssessment;
use App\Support\BackupHealth\TenantBackupHealthResolver;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use Filament\Facades\Filament;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use Filament\Resources\Pages\ListRecords;
use Illuminate\Database\Eloquent\ModelNotFoundException;
@ -34,7 +32,7 @@ public function mountAction(string $name, array $arguments = [], array $context
public function mount(): void
{
$this->syncCanonicalAdminTenantFilterState();
$this->syncCanonicalAdminEnvironmentFilterState();
parent::mount();
}
@ -59,13 +57,13 @@ private function tableHasRecords(): bool
return $this->getTableRecords()->count() > 0;
}
private function syncCanonicalAdminTenantFilterState(): void
private function syncCanonicalAdminEnvironmentFilterState(): void
{
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
tenantSensitiveFilters: [],
environmentSensitiveFilters: [],
request: request(),
tenantFilterName: null,
environmentFilterName: null,
);
}
@ -75,9 +73,9 @@ public function getSubheading(): ?string
return null;
}
$tenant = BackupScheduleResource::panelTenantContext();
$tenant = BackupScheduleResource::panelTenantContext();
if ($tenant === null) {
if ($tenant === null) {
return 'One or more enabled schedules need follow-up.';
}

View File

@ -4,7 +4,7 @@
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\BackupSetResource\Pages;
use App\Filament\Resources\BackupSetResource\RelationManagers\BackupItemsRelationManager;
use App\Jobs\BulkBackupSetDeleteJob;
@ -45,7 +45,6 @@
use Filament\Actions\ActionGroup;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Infolists;
use Filament\Notifications\Notification;
@ -64,7 +63,7 @@ class BackupSetResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = BackupSet::class;

View File

@ -4,7 +4,7 @@
use App\Filament\Resources\BackupSetResource;
use App\Support\BackupHealth\TenantBackupHealthAssessment;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use Filament\Resources\Pages\ListRecords;
class ListBackupSets extends ListRecords
@ -13,10 +13,10 @@ class ListBackupSets extends ListRecords
public function mount(): void
{
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
request: request(),
tenantFilterName: null,
environmentFilterName: null,
);
parent::mount();

View File

@ -4,13 +4,14 @@
namespace App\Filament\Resources;
use App\Filament\Concerns\CleansAdminTenantResourceQueryParameter;
use App\Filament\Pages\BaselineCompareMatrix;
use App\Filament\Resources\BaselineProfileResource\Pages;
use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot;
use App\Models\BaselineTenantAssignment;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Audit\WorkspaceAuditLogger;
@ -21,11 +22,11 @@
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Baselines\BaselineScope;
use App\Support\Baselines\BaselineCaptureMode;
use App\Support\Baselines\BaselineFullContentRolloutGate;
use App\Support\Baselines\BaselineProfileStatus;
use App\Support\Baselines\BaselineReasonCodes;
use App\Support\Baselines\BaselineScope;
use App\Support\Baselines\Compare\CompareStrategyRegistry;
use App\Support\Filament\FilterOptionCatalog;
use App\Support\Inventory\InventoryPolicyTypeMeta;
@ -61,16 +62,18 @@
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use InvalidArgumentException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Unique;
use InvalidArgumentException;
use UnitEnum;
class BaselineProfileResource extends Resource
{
use CleansAdminTenantResourceQueryParameter;
protected static bool $isDiscovered = false;
protected static bool $isScopedToTenant = false;

View File

@ -4,6 +4,7 @@
namespace App\Filament\Resources;
use App\Filament\Concerns\CleansAdminTenantResourceQueryParameter;
use App\Filament\Resources\BaselineSnapshotResource\Pages;
use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot;
@ -25,9 +26,9 @@
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceType;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthEnvelope;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\SurfaceCompressionContext;
use App\Support\Workspaces\WorkspaceContext;
use BackedEnum;
@ -44,6 +45,8 @@
class BaselineSnapshotResource extends Resource
{
use CleansAdminTenantResourceQueryParameter;
protected static bool $isDiscovered = false;
protected static bool $isScopedToTenant = false;

View File

@ -5,7 +5,7 @@
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\ScopesGlobalSearchToTenant;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\EntraGroupResource\Pages;
use App\Models\EntraGroup;
use App\Models\ManagedEnvironment;
@ -39,7 +39,7 @@ class EntraGroupResource extends Resource
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use ScopesGlobalSearchToTenant;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static bool $isScopedToTenant = false;

View File

@ -7,7 +7,7 @@
use App\Models\User;
use App\Services\Directory\EntraGroupSyncService;
use App\Support\Auth\Capabilities;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\OperationRunLinks;
use App\Support\OpsUx\OpsUxBrowserEvents;
use App\Support\OpsUx\ProviderOperationStartResultPresenter;
@ -22,10 +22,10 @@ class ListEntraGroups extends ListRecords
public function mount(): void
{
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
request: request(),
tenantFilterName: null,
environmentFilterName: null,
);
if (

View File

@ -4,47 +4,46 @@
namespace App\Filament\Resources;
use App\Exceptions\Entitlements\WorkspaceEntitlementBlockedException;
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EnvironmentReviewResource\Pages;
use App\Exceptions\Entitlements\WorkspaceEntitlementBlockedException;
use App\Models\EvidenceSnapshot;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\EnvironmentReview;
use App\Models\EnvironmentReviewSection;
use App\Models\EvidenceSnapshot;
use App\Models\ManagedEnvironment;
use App\Models\ReviewPack;
use App\Models\User;
use App\Services\ReviewPackService;
use App\Services\EnvironmentReviews\EnvironmentReviewService;
use App\Services\ReviewPackService;
use App\Support\Auth\Capabilities;
use App\Support\Auth\UiTooltips as AuthUiTooltips;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\EnvironmentReviewStatus;
use App\Support\Findings\FindingOutcomeSemantics;
use App\Support\Navigation\NavigationScope;
use App\Support\OperationRunLinks;
use App\Support\OperationRunType;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\Rbac\UiEnforcement;
use App\Support\ReasonTranslation\ReasonPresenter;
use App\Support\ReviewPackStatus;
use App\Support\Rbac\UiEnforcement;
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\EnvironmentReviewStatus;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceInspectAffordance;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceType;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthEnvelope;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\SurfaceCompressionContext;
use BackedEnum;
use Filament\Actions;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Infolists\Components\RepeatableEntry;
use Filament\Infolists\Components\TextEntry;
@ -66,7 +65,7 @@ class EnvironmentReviewResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static bool $isDiscovered = false;
@ -317,7 +316,7 @@ public static function table(Table $table): Table
->persistFiltersInSession()
->persistSearchInSession()
->persistSortInSession()
->recordUrl(fn (EnvironmentReview $record): string => static::tenantScopedUrl('view', ['record' => $record], $record->tenant))
->recordUrl(fn (EnvironmentReview $record): string => static::environmentScopedUrl('view', ['record' => $record], $record->tenant))
->columns([
Tables\Columns\TextColumn::make('status')
->badge()
@ -464,7 +463,7 @@ public static function executeCreateReview(array $data): void
->actions([
Actions\Action::make('view_review')
->label(__('localization.review.view_review'))
->url(static::tenantScopedUrl('view', ['record' => $review], $tenant)),
->url(static::environmentScopedUrl('view', ['record' => $review], $tenant)),
])
->send();
@ -613,11 +612,10 @@ public static function executeExport(EnvironmentReview $review): void
/**
* @param array<string, mixed> $parameters
*/
public static function tenantScopedUrl(
public static function environmentScopedUrl(
string $page = 'index',
array $parameters = [],
?ManagedEnvironment $tenant = null,
?string $panel = null,
): string {
$panelId = 'admin';
@ -881,7 +879,7 @@ private static function summaryContextLinks(EnvironmentReview $record, bool $cus
$links[] = [
'title' => __('localization.review.customer_workspace'),
'label' => __('localization.review.open_customer_workspace'),
'url' => CustomerReviewWorkspace::tenantPrefilterUrl($record->tenant),
'url' => CustomerReviewWorkspace::environmentFilterUrl($record->tenant),
'description' => __('localization.review.customer_workspace_description'),
];
}

View File

@ -6,19 +6,19 @@
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\EnvironmentReview;
use App\Models\ManagedEnvironment;
use App\Models\ReviewPack;
use App\Models\User;
use App\Services\ReviewPackService;
use App\Services\Audit\WorkspaceAuditLogger;
use App\Services\EnvironmentReviews\EnvironmentReviewLifecycleService;
use App\Services\EnvironmentReviews\EnvironmentReviewService;
use App\Services\ReviewPackService;
use App\Support\Audit\AuditActionId;
use App\Support\Auth\Capabilities;
use App\Support\EnvironmentReviewStatus;
use App\Support\Rbac\UiEnforcement;
use App\Support\ReviewPackStatus;
use App\Support\EnvironmentReviewStatus;
use App\Support\Ui\GovernanceActions\GovernanceActionCatalog;
use Filament\Actions;
use Filament\Forms\Components\Textarea;
@ -302,7 +302,7 @@ private function createNextReviewAction(): Actions\Action
return;
}
$this->redirect(EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $nextReview], $nextReview->tenant));
$this->redirect(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $nextReview], $nextReview->tenant));
}),
)
->requireCapability(Capabilities::ENVIRONMENT_REVIEW_MANAGE)

View File

@ -6,10 +6,9 @@
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EvidenceSnapshotResource\Pages;
use App\Filament\Resources\ReviewPackResource;
use App\Models\EvidenceSnapshot;
use App\Models\EvidenceSnapshotItem;
use App\Models\ManagedEnvironment;
@ -21,8 +20,8 @@
use App\Support\Badges\BadgeRenderer;
use App\Support\Evidence\EvidenceCompletenessState;
use App\Support\Evidence\EvidenceSnapshotStatus;
use App\Support\Navigation\RelatedContextEntry;
use App\Support\Navigation\NavigationScope;
use App\Support\Navigation\RelatedContextEntry;
use App\Support\OperationCatalog;
use App\Support\OperationRunLinks;
use App\Support\OperationRunOutcome;
@ -35,13 +34,12 @@
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceType;
use App\Support\Ui\GovernanceActions\GovernanceActionCatalog;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthEnvelope;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\SurfaceCompressionContext;
use BackedEnum;
use Filament\Actions;
use Filament\Facades\Filament;
use Filament\Forms\Components\Textarea;
use Filament\Infolists\Components\RepeatableEntry;
use Filament\Infolists\Components\TextEntry;
@ -66,7 +64,7 @@ class EvidenceSnapshotResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = EvidenceSnapshot::class;
@ -311,7 +309,7 @@ public static function relatedContextEntries(EvidenceSnapshot $record): array
label: 'Customer workspace',
value: $record->tenant->name,
secondaryValue: 'Open the customer-safe review workspace prefiltered to this tenant.',
targetUrl: CustomerReviewWorkspace::tenantPrefilterUrl($record->tenant),
targetUrl: CustomerReviewWorkspace::environmentFilterUrl($record->tenant),
targetKind: 'canonical_page',
priority: 30,
actionLabel: 'Open customer workspace',

View File

@ -6,9 +6,8 @@
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\FindingExceptionResource\Pages;
use App\Filament\Resources\FindingResource;
use App\Models\FindingException;
use App\Models\FindingExceptionEvidenceReference;
use App\Models\ManagedEnvironment;
@ -31,7 +30,6 @@
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
@ -56,7 +54,7 @@ class FindingExceptionResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = FindingException::class;

View File

@ -4,13 +4,13 @@
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\FindingResource\Pages;
use App\Filament\Support\NormalizedDiffSurface;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\PolicyVersion;
use App\Models\ManagedEnvironment;
use App\Models\PolicyVersion;
use App\Models\User;
use App\Services\Auth\ManagedEnvironmentAccessScopeResolver;
use App\Services\Drift\DriftFindingDiffBuilder;
@ -22,8 +22,8 @@
use App\Support\Badges\BadgeRenderer;
use App\Support\Filament\FilterOptionCatalog;
use App\Support\Filament\FilterPresets;
use App\Support\Findings\FindingOutcomeSemantics;
use App\Support\Filament\TablePaginationProfiles;
use App\Support\Findings\FindingOutcomeSemantics;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\Navigation\CrossResourceNavigationMatrix;
use App\Support\Navigation\NavigationScope;
@ -69,7 +69,7 @@ class FindingResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = Finding::class;
@ -1229,7 +1229,7 @@ public static function table(Table $table): Table
}
}
$body = "Resolved {$resolvedCount} finding".($resolvedCount === 1 ? '' : 's')." pending verification.";
$body = "Resolved {$resolvedCount} finding".($resolvedCount === 1 ? '' : 's').' pending verification.';
if ($skippedCount > 0) {
$body .= " Skipped {$skippedCount}.";
}

View File

@ -11,7 +11,7 @@
use App\Models\User;
use App\Services\Findings\FindingWorkflowService;
use App\Support\Auth\Capabilities;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\Rbac\UiEnforcement;
use App\Support\Rbac\UiTooltips;
use Filament\Actions;
@ -49,7 +49,7 @@ public function mountAction(string $name, array $arguments = [], array $context
public function mount(): void
{
$this->syncCanonicalAdminTenantFilterState();
$this->syncCanonicalAdminEnvironmentFilterState();
parent::mount();
$this->applyRequestedDashboardPrefilter();
@ -264,13 +264,13 @@ protected function buildAllMatchingQuery(): Builder
return $query;
}
private function syncCanonicalAdminTenantFilterState(): void
private function syncCanonicalAdminEnvironmentFilterState(): void
{
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
tenantSensitiveFilters: ['scope_key', 'run_ids'],
environmentSensitiveFilters: ['scope_key', 'run_ids'],
request: request(),
tenantFilterName: null,
environmentFilterName: null,
);
}

View File

@ -5,7 +5,7 @@
use App\Filament\Clusters\Inventory\InventoryCluster;
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\InventoryItemResource\Pages;
use App\Models\InventoryItem;
use App\Models\ManagedEnvironment;
@ -28,8 +28,8 @@
use Closure;
use Filament\Facades\Filament;
use Filament\Infolists\Components\TextEntry;
use Filament\Panel;
use Filament\Infolists\Components\ViewEntry;
use Filament\Panel;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
@ -37,15 +37,15 @@
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use UnitEnum;
class InventoryItemResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = InventoryItem::class;

View File

@ -12,7 +12,7 @@
use App\Services\Inventory\InventorySyncService;
use App\Services\OperationRunService;
use App\Support\Auth\Capabilities;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use App\Support\Inventory\InventoryPolicyTypeMeta;
use App\Support\OperationRunLinks;
use App\Support\OperationRunType;
@ -28,8 +28,8 @@
use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\ListRecords;
use Filament\Support\Enums\Width;
use Filament\Support\Enums\Size;
use Filament\Support\Enums\Width;
class ListInventoryItems extends ListRecords
{
@ -41,16 +41,16 @@ class ListInventoryItems extends ListRecords
public function mount(): void
{
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
request: request(),
tenantFilterName: null,
environmentFilterName: null,
);
$tenant = static::resolveTenantContextForCurrentPanel();
if ($tenant instanceof ManagedEnvironment) {
app(WorkspaceContext::class)->rememberTenantContext($tenant, request());
app(WorkspaceContext::class)->rememberEnvironmentContext($tenant, request());
}
parent::mount();

View File

@ -20,7 +20,7 @@ public function mount(int|string $record): void
$tenant = static::resolveTenantContextForCurrentPanel();
if ($tenant instanceof ManagedEnvironment) {
app(WorkspaceContext::class)->rememberTenantContext($tenant, request());
app(WorkspaceContext::class)->rememberEnvironmentContext($tenant, request());
}
parent::mount($record);

View File

@ -191,19 +191,19 @@ public static function table(Table $table): Table
->all();
})
->default(function (): ?string {
$activeTenant = app(OperateHubShell::class)->activeEntitledTenant(request());
$activeEnvironment = app(OperateHubShell::class)->activeEntitledTenant(request());
if (! $activeTenant instanceof ManagedEnvironment) {
if (! $activeEnvironment instanceof ManagedEnvironment) {
return null;
}
$workspaceId = app(WorkspaceContext::class)->currentWorkspaceId();
if ($workspaceId === null || (int) $activeTenant->workspace_id !== (int) $workspaceId) {
if ($workspaceId === null || (int) $activeEnvironment->workspace_id !== (int) $workspaceId) {
return null;
}
return (string) $activeTenant->getKey();
return (string) $activeEnvironment->getKey();
})
->searchable(),
Tables\Filters\SelectFilter::make('type')

View File

@ -5,7 +5,7 @@
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\ScopesGlobalSearchToTenant;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\PolicyResource\Pages;
use App\Filament\Resources\PolicyResource\RelationManagers\VersionsRelationManager;
use App\Filament\Support\NormalizedSettingsSurface;
@ -13,8 +13,8 @@
use App\Jobs\BulkPolicyExportJob;
use App\Jobs\BulkPolicyUnignoreJob;
use App\Jobs\SyncPoliciesJob;
use App\Models\Policy;
use App\Models\ManagedEnvironment;
use App\Models\Policy;
use App\Models\User;
use App\Services\Auth\CapabilityResolver;
use App\Services\Intune\PolicyNormalizer;
@ -41,7 +41,6 @@
use Filament\Actions\ActionGroup;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\ViewEntry;
@ -63,7 +62,7 @@ class PolicyResource extends Resource
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use ScopesGlobalSearchToTenant;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = Policy::class;

View File

@ -3,7 +3,7 @@
namespace App\Filament\Resources\PolicyResource\Pages;
use App\Filament\Resources\PolicyResource;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use Filament\Resources\Pages\ListRecords;
class ListPolicies extends ListRecords
@ -12,7 +12,7 @@ class ListPolicies extends ListRecords
public function mount(): void
{
$this->syncCanonicalAdminTenantFilterState();
$this->syncCanonicalAdminEnvironmentFilterState();
parent::mount();
}
@ -31,13 +31,13 @@ protected function getTableEmptyStateActions(): array
];
}
private function syncCanonicalAdminTenantFilterState(): void
private function syncCanonicalAdminEnvironmentFilterState(): void
{
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
tenantSensitiveFilters: [],
environmentSensitiveFilters: [],
request: request(),
tenantFilterName: null,
environmentFilterName: null,
);
}
}

View File

@ -5,7 +5,7 @@
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\ScopesGlobalSearchToTenant;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\PolicyVersionResource\Pages;
use App\Filament\Support\NormalizedDiffSurface;
use App\Filament\Support\NormalizedSettingsSurface;
@ -14,8 +14,8 @@
use App\Jobs\BulkPolicyVersionRestoreJob;
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\PolicyVersion;
use App\Models\ManagedEnvironment;
use App\Models\PolicyVersion;
use App\Models\User;
use App\Services\Auth\CapabilityResolver;
use App\Services\Intune\AuditLogger;
@ -49,7 +49,6 @@
use Filament\Actions;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Infolists;
use Filament\Notifications\Notification;
@ -71,7 +70,7 @@ class PolicyVersionResource extends Resource
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use ScopesGlobalSearchToTenant;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = PolicyVersion::class;

View File

@ -3,7 +3,7 @@
namespace App\Filament\Resources\PolicyVersionResource\Pages;
use App\Filament\Resources\PolicyVersionResource;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use Filament\Resources\Pages\ListRecords;
class ListPolicyVersions extends ListRecords
@ -12,10 +12,10 @@ class ListPolicyVersions extends ListRecords
public function mount(): void
{
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
request: request(),
tenantFilterName: null,
environmentFilterName: null,
);
parent::mount();

View File

@ -203,20 +203,6 @@ public static function resolveRequestedEnvironment(): ?ManagedEnvironment
public static function resolveContextTenantExternalId(): ?string
{
$workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());
$contextTenantId = app(WorkspaceContext::class)->lastTenantId(request());
if ($workspaceId !== null && $contextTenantId !== null) {
$tenant = ManagedEnvironment::query()
->whereKey($contextTenantId)
->where('workspace_id', (int) $workspaceId)
->first();
if ($tenant instanceof ManagedEnvironment) {
return (string) $tenant->slug;
}
}
$tenant = static::resolveTenantContextForCurrentPanel();
if ($tenant instanceof ManagedEnvironment) {
@ -228,7 +214,7 @@ public static function resolveContextTenantExternalId(): ?string
public static function resolveTenantForCreate(): ?ManagedEnvironment
{
$tenantExternalId = static::resolveRequestedTenantExternalId() ?? static::resolveContextTenantExternalId();
$tenantExternalId = static::resolveRequestedTenantExternalId();
if (! is_string($tenantExternalId) || $tenantExternalId === '') {
return null;
@ -1676,11 +1662,6 @@ public static function getUrl(?string $name = null, array $parameters = [], bool
$tenantExternalId = null;
$isIndexUrl = $name === null || $name === 'index';
if (array_key_exists('tenant', $parameters)) {
$tenantExternalId = static::normalizeTenantExternalId($parameters['tenant']);
unset($parameters['tenant']);
}
if ($tenantExternalId === null && $tenant instanceof ManagedEnvironment) {
$tenantExternalId = (string) $tenant->slug;
}

View File

@ -6,7 +6,7 @@
use App\Exceptions\Hardening\ProviderAccessHardeningRequired;
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\RestoreRunResource\Pages;
use App\Jobs\BulkRestoreRunDeleteJob;
use App\Jobs\BulkRestoreRunForceDeleteJob;
@ -15,9 +15,9 @@
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\EntraGroup;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\RestoreRun;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Rules\SkipOrUuidRule;
@ -32,21 +32,21 @@
use App\Services\Operations\BulkSelectionIdentity;
use App\Services\Providers\ProviderOperationStartGate;
use App\Services\Providers\ProviderOperationStartResult;
use App\Support\Audit\AuditActionId;
use App\Support\Auth\Capabilities;
use App\Support\BackupQuality\BackupQualityResolver;
use App\Support\Audit\AuditActionId;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Filament\FilterOptionCatalog;
use App\Support\Filament\FilterPresets;
use App\Support\Navigation\NavigationScope;
use App\Support\OperationalControls\OperationalControlBlockedException;
use App\Support\OperationalControls\OperationalControlEvaluator;
use App\Support\OperationCatalog;
use App\Support\OperationRunLinks;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\OpsUx\OpsUxBrowserEvents;
use App\Support\OpsUx\ProviderOperationStartResultPresenter;
use App\Support\OperationalControls\OperationalControlBlockedException;
use App\Support\OperationalControls\OperationalControlEvaluator;
use App\Support\Rbac\UiEnforcement;
use App\Support\RestoreRunIdempotency;
use App\Support\RestoreRunStatus;
@ -63,7 +63,6 @@
use Filament\Actions\ActionGroup;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Infolists;
use Filament\Notifications\Notification;
@ -80,7 +79,6 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
@ -90,7 +88,7 @@ class RestoreRunResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = RestoreRun::class;

View File

@ -3,7 +3,7 @@
namespace App\Filament\Resources\RestoreRunResource\Pages;
use App\Filament\Resources\RestoreRunResource;
use App\Support\Filament\CanonicalAdminTenantFilterState;
use App\Support\Filament\CanonicalAdminEnvironmentFilterState;
use Filament\Resources\Pages\ListRecords;
use Illuminate\Database\Eloquent\ModelNotFoundException;
@ -30,10 +30,10 @@ public function mountAction(string $name, array $arguments = [], array $context
public function mount(): void
{
app(CanonicalAdminTenantFilterState::class)->sync(
app(CanonicalAdminEnvironmentFilterState::class)->sync(
$this->getTableFiltersSessionKey(),
request: request(),
tenantFilterName: null,
environmentFilterName: null,
);
parent::mount();

View File

@ -2,20 +2,19 @@
namespace App\Filament\Resources;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Exceptions\Entitlements\WorkspaceEntitlementBlockedException;
use App\Exceptions\ReviewPackEvidenceResolutionException;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EvidenceSnapshotResource as TenantEvidenceSnapshotResource;
use App\Filament\Resources\ReviewPackResource\Pages;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\ReviewPack;
use App\Models\User;
use App\Services\ReviewPackService;
use App\Support\Auth\Capabilities;
use App\Support\Auth\UiTooltips as AuthUiTooltips;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Navigation\NavigationScope;
@ -28,13 +27,12 @@
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceType;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthEnvelope;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\SurfaceCompressionContext;
use BackedEnum;
use Filament\Actions;
use Filament\Facades\Filament;
use Filament\Forms\Components\Toggle;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\ViewEntry;
@ -52,7 +50,7 @@
class ReviewPackResource extends Resource
{
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
protected static ?string $model = ReviewPack::class;
@ -204,14 +202,14 @@ public static function infolist(Schema $schema): Schema
->label('ManagedEnvironment review')
->formatStateUsing(fn (?int $state): string => $state ? '#'.$state : '—')
->url(fn (ReviewPack $record): ?string => $record->environmentReview && $record->tenant
? EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $record->environmentReview], $record->tenant)
? EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $record->environmentReview], $record->tenant)
: null)
->placeholder('—'),
TextEntry::make('customer_workspace')
->label('Customer workspace')
->state(fn (): string => 'Open workspace')
->url(fn (ReviewPack $record): ?string => $record->tenant instanceof ManagedEnvironment
? CustomerReviewWorkspace::tenantPrefilterUrl($record->tenant)
? CustomerReviewWorkspace::environmentFilterUrl($record->tenant)
: null)
->placeholder('—'),
TextEntry::make('summary.review_status')

View File

@ -6,10 +6,10 @@
use App\Filament\Concerns\InteractsWithTenantOwnedRecords;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedTenantRoutes;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Resources\StoredReportResource\Pages;
use App\Models\StoredReport;
use App\Models\ManagedEnvironment;
use App\Models\StoredReport;
use App\Models\User;
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeDomain;
@ -45,7 +45,7 @@ class StoredReportResource extends Resource
{
use InteractsWithTenantOwnedRecords;
use ResolvesPanelTenantContext;
use WorkspaceScopedTenantRoutes;
use WorkspaceScopedEnvironmentRoutes;
/**
* @var array<string, string>

View File

@ -6,9 +6,9 @@
use App\Exceptions\Entitlements\WorkspaceEntitlementBlockedException;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Services\ReviewPackService;
use App\Support\Auth\Capabilities;
@ -193,7 +193,7 @@ protected function getViewData(): array
'generationBlocked' => $generationBlocked,
'generationBlockReason' => $generationBlockReason,
'generationWarningReason' => $generationWarningReason,
'customerWorkspaceUrl' => $canView ? CustomerReviewWorkspace::tenantPrefilterUrl($tenant) : null,
'customerWorkspaceUrl' => $canView ? CustomerReviewWorkspace::environmentFilterUrl($tenant) : null,
'downloadUrl' => null,
'failedReason' => null,
'reviewUrl' => null,
@ -211,7 +211,7 @@ protected function getViewData(): array
$reviewUrl = null;
if ($latestPack->environmentReview && $canView) {
$reviewUrl = \App\Filament\Resources\EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $latestPack->environmentReview], $tenant);
$reviewUrl = \App\Filament\Resources\EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $latestPack->environmentReview], $tenant);
}
$failedReason = null;
@ -245,7 +245,7 @@ protected function getViewData(): array
'generationBlocked' => $generationBlocked,
'generationBlockReason' => $generationBlockReason,
'generationWarningReason' => $generationWarningReason,
'customerWorkspaceUrl' => $canView ? CustomerReviewWorkspace::tenantPrefilterUrl($tenant) : null,
'customerWorkspaceUrl' => $canView ? CustomerReviewWorkspace::environmentFilterUrl($tenant) : null,
'downloadUrl' => $downloadUrl,
'failedReason' => $failedReason,
'failedReasonDetail' => $failedReasonDetail,

View File

@ -4,8 +4,8 @@
namespace App\Filament\Widgets\Operations;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\User;
use App\Services\Auth\ManagedEnvironmentAccessScopeResolver;
use App\Support\OperateHub\OperateHubShell;
@ -27,7 +27,7 @@ class OperationsKpiHeader extends StatsOverviewWidget
protected function getPollingInterval(): ?string
{
$tenant = $this->activeTenant();
$tenant = $this->activeEnvironment();
if ($tenant instanceof ManagedEnvironment) {
return ActiveRuns::existForTenant($tenant) ? '10s' : null;
@ -119,7 +119,7 @@ protected function getStats(): array
];
}
private function activeTenant(): ?ManagedEnvironment
private function activeEnvironment(): ?ManagedEnvironment
{
$tenant = app(OperateHubShell::class)->activeEntitledTenant(request());
@ -128,7 +128,7 @@ private function activeTenant(): ?ManagedEnvironment
private function scopedOperationRunQuery(): ?Builder
{
$tenant = $this->activeTenant();
$tenant = $this->activeEnvironment();
if ($tenant instanceof ManagedEnvironment) {
return OperationRun::query()

View File

@ -4,8 +4,8 @@
namespace App\Http\Controllers;
use App\Support\Navigation\AdminSurfaceScope;
use App\Support\OperationRunLinks;
use App\Support\Tenants\TenantPageCategory;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Illuminate\Http\RedirectResponse;
@ -19,7 +19,7 @@ public function __invoke(Request $request): RedirectResponse
$workspaceContext = app(WorkspaceContext::class);
$workspaceContext->clearRememberedTenantContext($request);
$workspaceContext->clearRememberedEnvironmentContext($request);
$previousUrl = url()->previous();
@ -30,11 +30,11 @@ public function __invoke(Request $request): RedirectResponse
return redirect()->to(OperationRunLinks::index());
}
if ($this->isTenantScopedEvidencePath($previousPath)) {
if ($this->isEnvironmentScopedEvidencePath($previousPath)) {
return redirect()->route('admin.evidence.overview');
}
if (TenantPageCategory::fromPath($previousPath) === TenantPageCategory::TenantBound) {
if (AdminSurfaceScope::fromPath($previousPath) === AdminSurfaceScope::EnvironmentBound) {
$workspace = $workspaceContext->currentWorkspace($request);
if ($workspace !== null) {
@ -51,7 +51,7 @@ public function __invoke(Request $request): RedirectResponse
return redirect()->to((string) $previousUrl);
}
private function isTenantScopedEvidencePath(string $previousPath): bool
private function isEnvironmentScopedEvidencePath(string $previousPath): bool
{
if ($previousPath === '/admin/evidence') {
return true;

View File

@ -49,7 +49,7 @@ public function __invoke(Request $request, ManagedEnvironment $environment): Red
$workspaceContext->setCurrentWorkspace($workspace, $user, $request);
if (! $workspaceContext->rememberTenantContext($environment, $request)) {
if (! $workspaceContext->rememberEnvironmentContext($environment, $request)) {
abort(404);
}

View File

@ -8,9 +8,9 @@
use App\Models\User;
use App\Models\UserTenantPreference;
use App\Services\Tenants\TenantOperabilityService;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Tenants\TenantInteractionLane;
use App\Support\Tenants\TenantOperabilityQuestion;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@ -63,7 +63,7 @@ public function __invoke(Request $request): RedirectResponse
$this->persistLastTenant($user, $tenant);
if (! app(WorkspaceContext::class)->rememberTenantContext($tenant, $request)) {
if (! app(WorkspaceContext::class)->rememberEnvironmentContext($tenant, $request)) {
abort(404);
}

View File

@ -48,7 +48,7 @@ public function __invoke(Request $request): RedirectResponse
$prevWorkspaceId = $context->currentWorkspaceId($request);
$context->setCurrentWorkspace($workspace, $user, $request);
$context->rememberedTenant($request);
$context->rememberedEnvironment($request);
Filament::setTenant(null, true);
/** @var WorkspaceAuditLogger $auditLogger */

View File

@ -250,7 +250,7 @@ private function resolveCurrentTenant(): ManagedEnvironment
$tenant = Filament::getTenant();
if (! $tenant instanceof ManagedEnvironment) {
$tenant = app(WorkspaceContext::class)->rememberedTenant(request());
$tenant = app(WorkspaceContext::class)->rememberedEnvironment(request());
}
if (! $tenant instanceof ManagedEnvironment) {

View File

@ -11,8 +11,8 @@
use Filament\Models\Contracts\HasDefaultTenant;
use Filament\Models\Contracts\HasTenants;
use Filament\Panel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
@ -194,10 +194,10 @@ public function getDefaultTenant(Panel $panel): ?Model
$operability = app(TenantOperabilityService::class);
$rememberedTenant = $workspaceContext->rememberedTenant(request());
$rememberedEnvironment = $workspaceContext->rememberedEnvironment(request());
if ($rememberedTenant instanceof ManagedEnvironment && $this->canAccessTenant($rememberedTenant)) {
return $rememberedTenant;
if ($rememberedEnvironment instanceof ManagedEnvironment && $this->canAccessTenant($rememberedEnvironment)) {
return $rememberedEnvironment;
}
$tenantId = null;

View File

@ -120,7 +120,7 @@ private function resolvedTenant(): ?ManagedEnvironment
return null;
}
$tenantId = app(WorkspaceContext::class)->lastTenantId(request());
$tenantId = app(WorkspaceContext::class)->lastEnvironmentId(request());
if (! is_int($tenantId)) {
return null;

View File

@ -109,7 +109,7 @@ private function authorizeForDraft(
$viewability = app(TenantOperabilityService::class)->outcomeFor(
tenant: $tenant,
question: TenantOperabilityQuestion::TenantBoundViewability,
question: TenantOperabilityQuestion::EnvironmentBoundViewability,
actor: $user,
workspaceId: (int) $workspace->getKey(),
lane: TenantInteractionLane::AdministrativeManagement,

View File

@ -240,11 +240,11 @@ private function resolveCreateTenant(Workspace $workspace): ?ManagedEnvironment
$requestedEnvironmentId = request()->query('environment_id');
if (! is_numeric($requestedEnvironmentId)) {
$lastTenantId = app(WorkspaceContext::class)->lastTenantId(request());
$lastEnvironmentId = app(WorkspaceContext::class)->lastEnvironmentId(request());
if (is_int($lastTenantId)) {
if (is_int($lastEnvironmentId)) {
return ManagedEnvironment::query()
->whereKey($lastTenantId)
->whereKey($lastEnvironmentId)
->where('workspace_id', (int) $workspace->getKey())
->first();
}

View File

@ -2,35 +2,35 @@
namespace App\Providers\Filament;
use App\Filament\Clusters\Inventory\InventoryCluster;
use App\Filament\Pages\Auth\Login;
use App\Filament\Pages\BaselineCompareLanding;
use App\Filament\Pages\ChooseEnvironment;
use App\Filament\Pages\ChooseWorkspace;
use App\Filament\Pages\CrossEnvironmentComparePage;
use App\Filament\Pages\EnvironmentRequiredPermissions;
use App\Filament\Pages\Findings\FindingsHygieneReport;
use App\Filament\Pages\Findings\FindingsIntakeQueue;
use App\Filament\Pages\Findings\MyFindingsInbox;
use App\Filament\Pages\Governance\DecisionRegister;
use App\Filament\Pages\Governance\GovernanceInbox;
use App\Filament\Pages\Findings\MyFindingsInbox;
use App\Filament\Pages\InventoryCoverage;
use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
use App\Filament\Pages\NoAccess;
use App\Filament\Pages\Reviews\ReviewRegister;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Pages\Reviews\ReviewRegister;
use App\Filament\Pages\Settings\WorkspaceSettings;
use App\Filament\Pages\EnvironmentRequiredPermissions;
use App\Filament\Pages\WorkspaceOverview;
use App\Filament\Clusters\Inventory\InventoryCluster;
use App\Filament\Resources\AlertDeliveryResource;
use App\Filament\Resources\AlertDestinationResource;
use App\Filament\Resources\AlertRuleResource;
use App\Filament\Resources\BaselineProfileResource;
use App\Filament\Resources\BaselineSnapshotResource;
use App\Filament\Resources\EntraGroupResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\InventoryItemResource;
use App\Filament\Resources\PolicyResource;
use App\Filament\Resources\ProviderConnectionResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\Workspaces\WorkspaceResource;
use App\Models\User;
use App\Models\Workspace;
@ -39,14 +39,14 @@
use App\Services\Auth\WorkspaceRoleCapabilityMap;
use App\Support\Auth\Capabilities;
use App\Support\Filament\PanelThemeAsset;
use App\Support\Navigation\AdminSurfaceScope;
use App\Support\Navigation\NavigationScope;
use App\Support\Navigation\WorkspaceHubRegistry;
use App\Support\OperationRunLinks;
use App\Support\Tenants\TenantPageCategory;
use App\Support\Workspaces\WorkspaceContext;
use Filament\FontProviders\LocalFontProvider;
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\AuthenticateSession;
use Filament\FontProviders\LocalFontProvider;
use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Navigation\NavigationItem;
@ -189,7 +189,7 @@ public function panel(Panel $panel): Panel
)
->renderHook(
PanelsRenderHook::PAGE_START,
fn (): string => TenantPageCategory::fromRequest(request()) === TenantPageCategory::OnboardingWorkflow
fn (): string => AdminSurfaceScope::fromRequest(request()) === AdminSurfaceScope::OnboardingWorkflow
|| request()->routeIs('admin.workspace.managed-environments.index', 'filament.admin.pages.choose-environment')
? ''
: ((bool) config('tenantpilot.bulk_operations.progress_widget_enabled', true)
@ -242,7 +242,7 @@ public function panel(Panel $panel): Panel
SubstituteBindings::class,
'ensure-correct-guard:web',
'ensure-workspace-selected',
'ensure-filament-tenant-selected',
'ensure-environment-context-selected',
DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class,
])

View File

@ -106,7 +106,7 @@ public function evaluate(TenantOperabilityContext $context, TenantOperabilityQue
lifecycle: $lifecycle,
lane: $context->lane,
reasonCode: TenantOperabilityReasonCode::MissingCapability,
discoverable: $question === TenantOperabilityQuestion::AdministrativeDiscoverability || $question === TenantOperabilityQuestion::TenantBoundViewability,
discoverable: $question === TenantOperabilityQuestion::AdministrativeDiscoverability || $question === TenantOperabilityQuestion::EnvironmentBoundViewability,
requiredCapability: $context->requiredCapability,
metadata: $this->metadata($context),
);
@ -169,7 +169,7 @@ public function evaluate(TenantOperabilityContext $context, TenantOperabilityQue
return match ($question) {
TenantOperabilityQuestion::SelectorEligibility => $this->selectorEligibilityOutcome($context, $lifecycle),
TenantOperabilityQuestion::RememberedContextValidity => $this->rememberedContextOutcome($context, $lifecycle),
TenantOperabilityQuestion::TenantBoundViewability => $this->tenantBoundViewabilityOutcome($context, $lifecycle),
TenantOperabilityQuestion::EnvironmentBoundViewability => $this->tenantBoundViewabilityOutcome($context, $lifecycle),
TenantOperabilityQuestion::CanonicalLinkedRecordViewability => $this->canonicalViewabilityOutcome($context, $lifecycle),
TenantOperabilityQuestion::ArchiveEligibility => $this->archiveEligibilityOutcome($context, $lifecycle),
TenantOperabilityQuestion::RestoreEligibility => $this->restoreEligibilityOutcome($context, $lifecycle),
@ -375,11 +375,11 @@ private function rememberedContextOutcome(TenantOperabilityContext $context, Ten
private function tenantBoundViewabilityOutcome(TenantOperabilityContext $context, TenantLifecycle $lifecycle): TenantOperabilityOutcome
{
if ($context->lane !== TenantInteractionLane::AdministrativeManagement) {
return $this->wrongLaneOutcome($context, TenantOperabilityQuestion::TenantBoundViewability, $lifecycle);
return $this->wrongLaneOutcome($context, TenantOperabilityQuestion::EnvironmentBoundViewability, $lifecycle);
}
return TenantOperabilityOutcome::allow(
question: TenantOperabilityQuestion::TenantBoundViewability,
question: TenantOperabilityQuestion::EnvironmentBoundViewability,
lifecycle: $lifecycle,
lane: $context->lane,
discoverable: true,

View File

@ -181,7 +181,7 @@ public function removeTenantFromWorkspace(ManagedEnvironment $tenant, User $acto
'is_current' => false,
])->save();
app(WorkspaceContext::class)->clearRememberedTenantContext();
app(WorkspaceContext::class)->clearRememberedEnvironmentContext();
$this->auditLogger->logTenantLifecycleAction(
tenant: $tenant,

View File

@ -6,18 +6,18 @@
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Models\ProductUsageEvent;
use App\Models\ProviderConnection;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\Workspace;
use App\Support\Auth\PlatformCapabilities;
use App\Support\Onboarding\OnboardingLifecycleState;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\Auth\PlatformCapabilities;
use App\Support\ProductTelemetry\ProductUsageEventCatalog;
use App\Support\Providers\ProviderConsentStatus;
use App\Support\Providers\ProviderVerificationStatus;
@ -68,7 +68,7 @@ public function summaries(SystemConsoleWindow|string|null $window = null, ?Carbo
->map(static fn (mixed $workspaceId): int => (int) $workspaceId)
->all();
$activeTenants = ManagedEnvironment::query()
$activeEnvironments = ManagedEnvironment::query()
->whereIn('workspace_id', $workspaceIds)
->whereNull('deleted_at')
->where('lifecycle_status', '!=', ManagedEnvironment::STATUS_ARCHIVED)
@ -76,7 +76,7 @@ public function summaries(SystemConsoleWindow|string|null $window = null, ?Carbo
->orderBy('id')
->get(['id', 'workspace_id', 'slug', 'name', 'lifecycle_status']);
$tenantsByWorkspace = $activeTenants->groupBy(static fn (ManagedEnvironment $tenant): int => (int) $tenant->workspace_id);
$tenantsByWorkspace = $activeEnvironments->groupBy(static fn (ManagedEnvironment $tenant): int => (int) $tenant->workspace_id);
$latestOnboardingSessions = ManagedEnvironmentOnboardingSession::query()
->whereIn('workspace_id', $workspaceIds)

View File

@ -8,36 +8,35 @@
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\BackupScheduleResource;
use App\Filament\Resources\BackupSetResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\FindingExceptionResource;
use App\Filament\Resources\FindingResource;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\EnvironmentReview;
use App\Models\EvidenceSnapshot;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\EnvironmentReview;
use App\Models\User;
use App\Services\Intune\ManagedEnvironmentRequiredPermissionsViewModelBuilder;
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\BackupHealth\BackupHealthActionTarget;
use App\Support\BackupHealth\TenantBackupHealthAssessment;
use App\Support\BackupHealth\TenantBackupHealthResolver;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Baselines\TenantGovernanceAggregate;
use App\Support\Baselines\TenantGovernanceAggregateResolver;
use App\Support\Links\RequiredPermissionsLinks;
use App\Support\OperationCatalog;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunLinks;
use App\Support\OperationRunOutcome;
use App\Support\OpsUx\ActiveRuns;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\RestoreSafety\RestoreResultAttention;
use App\Support\RestoreSafety\RestoreSafetyResolver;
use App\Support\Tenants\TenantRecoveryTriagePresentation;
use App\Support\Verification\VerificationReportOverall;
@ -1084,8 +1083,7 @@ private function metricCard(
string $icon,
array $action,
?array $chart = null,
): array
{
): array {
return array_merge([
'key' => $key,
'label' => $label,
@ -1165,8 +1163,8 @@ private function environmentReviewAction(ManagedEnvironment $tenant, ?User $user
if ($canOpen) {
$url = $review instanceof EnvironmentReview
? EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant)
: EnvironmentReviewResource::tenantScopedUrl('index', tenant: $tenant);
? EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant)
: EnvironmentReviewResource::environmentScopedUrl('index', tenant: $tenant);
}
return $this->actionPayload(
@ -1185,7 +1183,7 @@ private function continueReviewAction(ManagedEnvironment $tenant, ?User $user, E
return $this->actionPayload(
label: $this->overviewText('action_continue_review'),
url: $canContinue ? EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant) : null,
url: $canContinue ? EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant) : null,
helperText: $canContinue ? null : $this->overviewText('helper_continue_review_requires_manage'),
);
}
@ -1234,7 +1232,7 @@ private function customerWorkspaceAction(ManagedEnvironment $tenant, ?User $user
if ($canOpenWorkspace) {
$url = $reviewPack instanceof ReviewPack && $user->can(Capabilities::REVIEW_PACK_VIEW, $tenant)
? ReviewPackResource::getUrl('view', ['record' => $reviewPack], tenant: $tenant)
: CustomerReviewWorkspace::tenantPrefilterUrl($tenant);
: CustomerReviewWorkspace::environmentFilterUrl($tenant);
}
return $this->actionPayload(
@ -1986,4 +1984,4 @@ private function overviewText(string $key, array $replace = []): string
{
return (string) __('localization.dashboard.overview.'.$key, $replace);
}
}
}

View File

@ -12,9 +12,9 @@
use Illuminate\Session\Store;
use Illuminate\Support\Arr;
final class CanonicalAdminTenantFilterState
final class CanonicalAdminEnvironmentFilterState
{
private const STATE_PREFIX = 'filament.admin_tenant_filter_state';
private const STATE_PREFIX = 'filament.admin_environment_filter_state';
public function __construct(
private readonly OperateHubShell $operateHubShell,
@ -25,20 +25,20 @@ public function currentFilterValue(
string $filtersSessionKey,
?array $tableFilters = null,
?Request $request = null,
?string $tenantFilterName = 'managed_environment_id',
?string $environmentFilterName = 'managed_environment_id',
): ?string {
if ($tenantFilterName === null) {
if ($environmentFilterName === null) {
return null;
}
$tableFilterValue = data_get($tableFilters ?? [], "{$tenantFilterName}.value");
$tableFilterValue = data_get($tableFilters ?? [], "{$environmentFilterName}.value");
if (is_scalar($tableFilterValue) && (string) $tableFilterValue !== '') {
return (string) $tableFilterValue;
}
$persistedFilters = $this->session($request)->get($filtersSessionKey, []);
$persistedValue = data_get(is_array($persistedFilters) ? $persistedFilters : [], "{$tenantFilterName}.value");
$persistedValue = data_get(is_array($persistedFilters) ? $persistedFilters : [], "{$environmentFilterName}.value");
if (! is_scalar($persistedValue) || (string) $persistedValue === '') {
return null;
@ -48,14 +48,14 @@ public function currentFilterValue(
}
/**
* @param array<int, string> $tenantSensitiveFilters
* @param array<int, string> $environmentSensitiveFilters
*/
public function sync(
string $filtersSessionKey,
array $tenantSensitiveFilters = [],
array $environmentSensitiveFilters = [],
?Request $request = null,
?string $tenantFilterName = 'managed_environment_id',
string $tenantAttribute = 'id',
?string $environmentFilterName = 'managed_environment_id',
string $environmentAttribute = 'id',
): void {
$session = $this->session($request);
@ -73,27 +73,27 @@ public function sync(
);
}
$activeTenant = $this->operateHubShell->activeEntitledTenant($request);
$resolvedTenantId = $activeTenant instanceof ManagedEnvironment ? (string) $activeTenant->getKey() : null;
$activeEnvironment = $this->operateHubShell->activeEntitledTenant($request);
$resolvedEnvironmentId = $activeEnvironment instanceof ManagedEnvironment ? (string) $activeEnvironment->getKey() : null;
$stateKey = $this->stateKey($filtersSessionKey);
$previousTenantId = $session->get($stateKey);
$previousEnvironmentId = $session->get($stateKey);
if ($previousTenantId !== $resolvedTenantId) {
foreach ($tenantSensitiveFilters as $filterName) {
if ($previousEnvironmentId !== $resolvedEnvironmentId) {
foreach ($environmentSensitiveFilters as $filterName) {
Arr::forget($persistedFilters, $filterName);
}
}
if ($tenantFilterName !== null) {
$tenantFilterValue = match ($tenantAttribute) {
'external_id' => $activeTenant?->external_id,
default => $resolvedTenantId,
if ($environmentFilterName !== null) {
$environmentFilterValue = match ($environmentAttribute) {
'external_id' => $activeEnvironment?->external_id,
default => $resolvedEnvironmentId,
};
if ($tenantFilterValue !== null) {
data_set($persistedFilters, "{$tenantFilterName}.value", $tenantFilterValue);
if ($environmentFilterValue !== null) {
data_set($persistedFilters, "{$environmentFilterName}.value", $environmentFilterValue);
} else {
Arr::forget($persistedFilters, $tenantFilterName);
Arr::forget($persistedFilters, $environmentFilterName);
}
}
@ -103,7 +103,7 @@ public function sync(
$session->put($filtersSessionKey, $persistedFilters);
}
$session->put($stateKey, $resolvedTenantId);
$session->put($stateKey, $resolvedEnvironmentId);
}
/**

View File

@ -9,24 +9,23 @@
use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\AlertDeliveryResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\FindingExceptionResource;
use App\Filament\Resources\FindingResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\AlertDelivery;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentTriageReview;
use App\Models\OperationRun;
use App\Models\User;
use App\Models\Workspace;
use App\Services\EnvironmentReviews\EnvironmentReviewRegisterService;
use App\Support\Auth\Capabilities;
use App\Support\BackupHealth\TenantBackupHealthResolver;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\OperationRunLinks;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use App\Support\PortfolioTriage\ManagedEnvironmentTriageReviewStateResolver;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use App\Support\RestoreSafety\RestoreSafetyResolver;
use Illuminate\Support\Str;
@ -550,7 +549,7 @@ private function reviewFollowUpSection(
'summary' => $this->reviewSummary($followUpCount, $changedCount),
'dominant_action_label' => 'Open customer review workspace',
'dominant_action_url' => $selectedTenant instanceof ManagedEnvironment
? $this->appendQuery(CustomerReviewWorkspace::tenantPrefilterUrl($selectedTenant), $navigationContext?->toQuery() ?? [])
? $this->appendQuery(CustomerReviewWorkspace::environmentFilterUrl($selectedTenant), $navigationContext?->toQuery() ?? [])
: $this->appendQuery(CustomerReviewWorkspace::getUrl(panel: 'admin'), $navigationContext?->toQuery() ?? []),
'entries' => array_slice($rawEntries, 0, self::PREVIEW_LIMIT),
'empty_state' => $selectedTenant instanceof ManagedEnvironment
@ -609,12 +608,12 @@ private function orderedIntakeFindingsQuery(\Illuminate\Database\Eloquent\Builde
{
return $query
->orderByRaw(
"case
'case
when due_at is not null and due_at < ? then 0
when status = ? then 1
when status = ? then 2
else 3
end asc",
end asc',
[now(), Finding::STATUS_REOPENED, Finding::STATUS_NEW],
)
->orderByRaw('case when due_at is null then 1 else 0 end asc')
@ -724,13 +723,13 @@ private function orderedFindingExceptionsQuery(\Illuminate\Database\Eloquent\Bui
{
return $query
->orderByRaw(
"case
'case
when status = ? then 0
when current_validity_state = ? then 1
when current_validity_state = ? then 2
when current_validity_state = ? then 3
else 4
end asc",
end asc',
[
FindingException::STATUS_PENDING,
FindingException::VALIDITY_EXPIRED,
@ -909,8 +908,8 @@ private function reviewEntry(
: null,
]));
$destinationUrl = $latestPublishedReview !== null
? EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $latestPublishedReview], $tenant)
: CustomerReviewWorkspace::tenantPrefilterUrl($tenant);
? EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $latestPublishedReview], $tenant)
: CustomerReviewWorkspace::environmentFilterUrl($tenant);
return [
'family_key' => 'review_follow_up',

View File

@ -4,11 +4,11 @@
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Support\Navigation\AdminSurfaceScope;
use App\Support\Navigation\NavigationScope;
use App\Support\Navigation\WorkspaceHubRegistry;
use App\Support\Navigation\WorkspaceSidebarNavigation;
use App\Support\OperateHub\OperateHubShell;
use App\Support\Tenants\TenantPageCategory;
use App\Support\Workspaces\WorkspaceContext;
use Closure;
use Filament\Facades\Filament;
@ -16,7 +16,7 @@
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureFilamentTenantSelected
class EnsureEnvironmentContextSelected
{
/**
* @param Closure(Request): Response $next
@ -100,7 +100,7 @@ public function handle(Request $request, Closure $next): Response
return redirect()->route('filament.admin.pages.choose-environment');
}
if ($resolvedContext->pageCategory === TenantPageCategory::TenantBound && ! $resolvedContext->hasTenant()) {
if ($resolvedContext->pageCategory === AdminSurfaceScope::EnvironmentBound && ! $resolvedContext->hasTenant()) {
abort(404);
}
@ -116,7 +116,7 @@ public function handle(Request $request, Closure $next): Response
$resolvedContext->hasTenant()
&& (
! $this->isWorkspaceScopedPageWithTenant($path)
&& $resolvedContext->pageCategory === TenantPageCategory::TenantBound
&& $resolvedContext->pageCategory === AdminSurfaceScope::EnvironmentBound
)
) {
Filament::setTenant($resolvedContext->tenant, true);
@ -175,7 +175,7 @@ private function isLivewireUpdatePath(string $path): bool
private function isCanonicalWorkspaceRecordViewerPath(string $path): bool
{
return TenantPageCategory::fromPath($path) === TenantPageCategory::CanonicalWorkspaceRecordViewer;
return AdminSurfaceScope::fromPath($path) === AdminSurfaceScope::CanonicalWorkspaceRecordViewer;
}
private function requestHasExplicitTenantHint(Request $request): bool

View File

@ -2,18 +2,18 @@
declare(strict_types=1);
namespace App\Support\Tenants;
namespace App\Support\Navigation;
use App\Support\Navigation\WorkspaceHubRegistry;
use App\Support\Tenants\TenantInteractionLane;
use Illuminate\Http\Request;
enum TenantPageCategory: string
enum AdminSurfaceScope: string
{
case WorkspaceWideSurface = 'workspace_wide_surface';
case WorkspaceScoped = 'workspace_scoped';
case WorkspaceChooserException = 'workspace_chooser_exception';
case TenantBound = 'tenant_bound';
case TenantScopedEvidence = 'tenant_scoped_evidence';
case EnvironmentBound = 'environment_bound';
case EnvironmentScopedEvidence = 'environment_scoped_evidence';
case OnboardingWorkflow = 'onboarding_workflow';
case CanonicalWorkspaceRecordViewer = 'canonical_workspace_record_viewer';
@ -46,7 +46,7 @@ public static function fromPath(string $path): self
str_starts_with($normalizedPath, '/admin/evidence/')
&& ! str_starts_with($normalizedPath, '/admin/evidence/overview')
) {
return self::TenantScopedEvidence;
return self::EnvironmentScopedEvidence;
}
if (preg_match('#^/admin/onboarding(?:/[^/]+)?$#', $normalizedPath) === 1) {
@ -54,13 +54,13 @@ public static function fromPath(string $path): self
}
if (preg_match('#^/admin/workspaces/[^/]+/environments/[^/]+(?:/|$)#', $normalizedPath) === 1) {
return self::TenantBound;
return self::EnvironmentBound;
}
return self::WorkspaceScoped;
}
public function allowsQueryTenantHints(): bool
public function allowsQueryEnvironmentHints(): bool
{
return match ($this) {
self::WorkspaceWideSurface, self::WorkspaceScoped, self::OnboardingWorkflow => true,
@ -68,7 +68,7 @@ public function allowsQueryTenantHints(): bool
};
}
public function allowsRememberedTenantRestore(): bool
public function allowsRememberedEnvironmentRestore(): bool
{
return match ($this) {
self::WorkspaceScoped, self::OnboardingWorkflow, self::CanonicalWorkspaceRecordViewer => true,
@ -76,7 +76,7 @@ public function allowsRememberedTenantRestore(): bool
};
}
public function allowsTenantlessState(): bool
public function allowsEnvironmentlessState(): bool
{
return match ($this) {
self::WorkspaceWideSurface,
@ -88,7 +88,7 @@ public function allowsTenantlessState(): bool
};
}
public function forcesTenantlessShellContext(): bool
public function forcesEnvironmentlessShellContext(): bool
{
return match ($this) {
self::WorkspaceWideSurface,
@ -98,17 +98,17 @@ public function forcesTenantlessShellContext(): bool
};
}
public function requiresExplicitTenant(): bool
public function requiresExplicitEnvironment(): bool
{
return match ($this) {
self::TenantBound, self::TenantScopedEvidence => true,
self::EnvironmentBound, self::EnvironmentScopedEvidence => true,
default => false,
};
}
public function lane(): TenantInteractionLane
{
return TenantInteractionLane::fromPageCategory($this);
return TenantInteractionLane::fromSurfaceScope($this);
}
private static function isWorkspaceWideSurfacePath(string $normalizedPath): bool

View File

@ -4,7 +4,6 @@
namespace App\Support\Navigation;
use App\Support\Tenants\TenantPageCategory;
use Illuminate\Http\Request;
final class NavigationScope
@ -17,8 +16,8 @@ public static function isWorkspaceSurface(?Request $request = null): bool
public static function isEnvironmentSurface(?Request $request = null): bool
{
return in_array(self::pageCategory($request), [
TenantPageCategory::TenantBound,
TenantPageCategory::TenantScopedEvidence,
AdminSurfaceScope::EnvironmentBound,
AdminSurfaceScope::EnvironmentScopedEvidence,
], true);
}
@ -27,9 +26,9 @@ public static function shouldRegisterEnvironmentNavigation(?Request $request = n
return self::isEnvironmentSurface($request);
}
public static function pageCategory(?Request $request = null): TenantPageCategory
public static function pageCategory(?Request $request = null): AdminSurfaceScope
{
return TenantPageCategory::fromPath(self::effectivePath($request));
return AdminSurfaceScope::fromPath(self::effectivePath($request));
}
private static function effectivePath(?Request $request = null): string

View File

@ -20,11 +20,11 @@
use App\Models\BaselineSnapshotItem;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\RestoreRun;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Auth\CapabilityResolver;
@ -39,7 +39,6 @@
use App\Support\Ui\DerivedState\DerivedStateFamily;
use App\Support\Ui\DerivedState\DerivedStateKey;
use App\Support\Ui\DerivedState\RequestScopedDerivedStateStore;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
@ -367,7 +366,7 @@ private function memoizedEntries(
context: [
'source_type' => $sourceType,
'surface' => $surface,
'active_tenant_id' => $this->activeTenantId(),
'active_tenant_id' => $this->activeEnvironmentId(),
'route_name' => request()?->route()?->getName(),
'user_id' => auth()->id(),
],
@ -631,7 +630,7 @@ private function snapshotPolicyVersionEntry(NavigationMatrixRule $rule, Baseline
return $this->policyVersionEntry(
rule: $rule,
policyVersionId: is_numeric($policyVersionId) ? (int) $policyVersionId : null,
tenantId: $this->activeTenantId(),
tenantId: $this->activeEnvironmentId(),
);
}
@ -1094,7 +1093,7 @@ private function contextForOperationRun(OperationRun $run): CanonicalNavigationC
);
}
private function activeTenantId(): ?int
private function activeEnvironmentId(): ?int
{
$tenant = app(OperateHubShell::class)->activeEntitledTenant(request());

View File

@ -10,9 +10,9 @@
use App\Services\Auth\CapabilityResolver;
use App\Services\Tenants\TenantOperabilityService;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Navigation\AdminSurfaceScope;
use App\Support\Navigation\WorkspaceHubRegistry;
use App\Support\Tenants\TenantOperabilityQuestion;
use App\Support\Tenants\TenantPageCategory;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Actions\Action;
use Filament\Facades\Filament;
@ -30,10 +30,10 @@ public function __construct(
public function scopeLabel(?Request $request = null): string
{
$activeTenant = $this->activeEntitledTenant($request);
$activeEnvironment = $this->activeEntitledTenant($request);
if ($activeTenant instanceof ManagedEnvironment) {
return __('localization.shell.environment_scope').': '.$activeTenant->name;
if ($activeEnvironment instanceof ManagedEnvironment) {
return __('localization.shell.environment_scope').': '.$activeEnvironment->name;
}
return __('localization.shell.all_environments');
@ -44,12 +44,12 @@ public function scopeLabel(?Request $request = null): string
*/
public function returnAffordance(?Request $request = null): ?array
{
$activeTenant = $this->activeEntitledTenant($request);
$activeEnvironment = $this->activeEntitledTenant($request);
if ($activeTenant instanceof ManagedEnvironment) {
if ($activeEnvironment instanceof ManagedEnvironment) {
return [
'label' => 'Back to '.$activeTenant->name,
'url' => ManagedEnvironmentLinks::viewUrl($activeTenant),
'label' => 'Back to '.$activeEnvironment->name,
'url' => ManagedEnvironmentLinks::viewUrl($activeEnvironment),
];
}
@ -135,7 +135,7 @@ private function buildResolvedContext(?Request $request = null): ResolvedShellCo
pageCategory: $pageCategory,
state: 'missing_workspace',
displayMode: 'recovery',
recoveryAction: $pageCategory === TenantPageCategory::WorkspaceChooserException ? 'none' : 'redirect_choose_workspace',
recoveryAction: $pageCategory === AdminSurfaceScope::WorkspaceChooserException ? 'none' : 'redirect_choose_workspace',
recoveryDestination: '/admin/choose-workspace',
recoveryReason: 'missing_workspace',
);
@ -157,7 +157,7 @@ private function buildResolvedContext(?Request $request = null): ResolvedShellCo
$recoveryReason = $routeTenant['reason'];
if ($pageCategory === TenantPageCategory::TenantBound && $recoveryReason !== null) {
if ($pageCategory === AdminSurfaceScope::EnvironmentBound && $recoveryReason !== null) {
return new ResolvedShellContext(
workspace: $workspace,
tenant: null,
@ -170,7 +170,7 @@ private function buildResolvedContext(?Request $request = null): ResolvedShellCo
);
}
if ($pageCategory->forcesTenantlessShellContext()) {
if ($pageCategory->forcesEnvironmentlessShellContext()) {
return new ResolvedShellContext(
workspace: $workspace,
tenant: null,
@ -225,13 +225,13 @@ private function buildResolvedContext(?Request $request = null): ResolvedShellCo
);
}
if ($pageCategory->allowsRememberedTenantRestore()) {
$rememberedTenant = $this->workspaceContext->rememberedTenant($request);
if ($pageCategory->allowsRememberedEnvironmentRestore()) {
$rememberedEnvironment = $this->workspaceContext->rememberedEnvironment($request);
if ($rememberedTenant instanceof ManagedEnvironment) {
if ($rememberedEnvironment instanceof ManagedEnvironment) {
return new ResolvedShellContext(
workspace: $workspace,
tenant: $rememberedTenant,
tenant: $rememberedEnvironment,
pageCategory: $pageCategory,
state: 'tenant_scoped',
displayMode: 'tenant_scoped',
@ -241,7 +241,7 @@ private function buildResolvedContext(?Request $request = null): ResolvedShellCo
}
}
if ($pageCategory->requiresExplicitTenant()) {
if ($pageCategory->requiresExplicitEnvironment()) {
return new ResolvedShellContext(
workspace: $workspace,
tenant: null,
@ -249,10 +249,10 @@ private function buildResolvedContext(?Request $request = null): ResolvedShellCo
state: 'missing_tenant',
displayMode: 'recovery',
workspaceSource: $workspaceSource,
recoveryAction: $pageCategory === TenantPageCategory::TenantScopedEvidence
recoveryAction: $pageCategory === AdminSurfaceScope::EnvironmentScopedEvidence
? 'redirect_evidence_overview'
: 'abort_not_found',
recoveryDestination: $pageCategory === TenantPageCategory::TenantScopedEvidence
recoveryDestination: $pageCategory === AdminSurfaceScope::EnvironmentScopedEvidence
? '/admin/evidence/overview'
: null,
recoveryReason: $recoveryReason ?? 'missing_tenant',
@ -272,7 +272,7 @@ private function buildResolvedContext(?Request $request = null): ResolvedShellCo
private function resolveValidatedFilamentTenant(
?Request $request = null,
?TenantPageCategory $pageCategory = null,
?AdminSurfaceScope $pageCategory = null,
?Workspace $workspace = null,
): ?ManagedEnvironment {
$tenant = Filament::getTenant();
@ -297,7 +297,7 @@ private function resolveValidatedRouteTenant(
?ManagedEnvironment $tenant,
Workspace $workspace,
?Request $request = null,
?TenantPageCategory $pageCategory = null,
?AdminSurfaceScope $pageCategory = null,
): array {
$pageCategory ??= $this->pageCategory($request);
@ -316,22 +316,22 @@ private function resolveValidatedRouteTenant(
private function resolveWorkspaceForPageCategory(
?ManagedEnvironment $tenant,
TenantPageCategory $pageCategory,
AdminSurfaceScope $pageCategory,
?Request $request = null,
): ?Workspace {
return match ($pageCategory) {
TenantPageCategory::TenantScopedEvidence => $this->workspaceContext->currentWorkspace($request),
TenantPageCategory::TenantBound => $this->workspaceContext->currentWorkspaceOrTenantWorkspace($tenant, $request),
default => $this->workspaceContext->currentWorkspaceOrTenantWorkspace($tenant, $request),
AdminSurfaceScope::EnvironmentScopedEvidence => $this->workspaceContext->currentWorkspace($request),
AdminSurfaceScope::EnvironmentBound => $this->workspaceContext->currentWorkspaceOrEnvironmentWorkspace($tenant, $request),
default => $this->workspaceContext->currentWorkspaceOrEnvironmentWorkspace($tenant, $request),
};
}
private function resolveValidatedQueryHintTenant(
?Request $request,
Workspace $workspace,
TenantPageCategory $pageCategory,
AdminSurfaceScope $pageCategory,
): array {
if (! $pageCategory->allowsQueryTenantHints()) {
if (! $pageCategory->allowsQueryEnvironmentHints()) {
return ['tenant' => null, 'reason' => null];
}
@ -350,7 +350,7 @@ private function resolveValidatedQueryHintTenant(
return ['tenant' => $queryTenant, 'reason' => null];
}
private function resolveRouteTenantCandidate(?Request $request = null, ?TenantPageCategory $pageCategory = null): ?ManagedEnvironment
private function resolveRouteTenantCandidate(?Request $request = null, ?AdminSurfaceScope $pageCategory = null): ?ManagedEnvironment
{
$route = $request?->route();
$pageCategory ??= $this->pageCategory($request);
@ -445,7 +445,7 @@ private function tenantValidationReason(
ManagedEnvironment $tenant,
Workspace $workspace,
?Request $request = null,
?TenantPageCategory $pageCategory = null,
?AdminSurfaceScope $pageCategory = null,
): ?string {
$pageCategory ??= $this->pageCategory($request);
@ -463,8 +463,8 @@ private function tenantValidationReason(
return 'not_member';
}
$question = $pageCategory === TenantPageCategory::TenantBound
? TenantOperabilityQuestion::TenantBoundViewability
$question = $pageCategory === AdminSurfaceScope::EnvironmentBound
? TenantOperabilityQuestion::EnvironmentBoundViewability
: TenantOperabilityQuestion::AdministrativeDiscoverability;
$allowed = $this->tenantOperabilityService->outcomeFor(
@ -480,13 +480,13 @@ private function tenantValidationReason(
return null;
}
return $pageCategory === TenantPageCategory::TenantBound
return $pageCategory === AdminSurfaceScope::EnvironmentBound
? 'inaccessible'
: 'not_operable';
}
private function pageCategory(?Request $request = null): TenantPageCategory
private function pageCategory(?Request $request = null): AdminSurfaceScope
{
return TenantPageCategory::fromRequest($request);
return AdminSurfaceScope::fromRequest($request);
}
}

View File

@ -6,14 +6,14 @@
use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use App\Support\Tenants\TenantPageCategory;
use App\Support\Navigation\AdminSurfaceScope;
final readonly class ResolvedShellContext
{
public function __construct(
public ?Workspace $workspace,
public ?ManagedEnvironment $tenant,
public TenantPageCategory $pageCategory,
public AdminSurfaceScope $pageCategory,
public string $state,
public string $displayMode,
public string $workspaceSource = 'none',

View File

@ -237,7 +237,7 @@ public static function related(OperationRun $run, ?ManagedEnvironment $tenant):
->first();
if ($review instanceof EnvironmentReview) {
$links['ManagedEnvironment Review'] = EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant);
$links['ManagedEnvironment Review'] = EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant);
}
}

View File

@ -4,18 +4,18 @@
namespace App\Support\SupportDiagnostics;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\FindingResource;
use App\Filament\Resources\ProviderConnectionResource;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\AuditLog;
use App\Models\EnvironmentReview;
use App\Models\Finding;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\ReviewPack;
use App\Models\StoredReport;
use App\Models\ManagedEnvironment;
use App\Models\EnvironmentReview;
use App\Models\User;
use App\Models\Workspace;
use App\Support\Ai\AiDataClassification;
@ -741,7 +741,7 @@ private function environmentReviewSection(?EnvironmentReview $review, ?ManagedEn
label: 'ManagedEnvironment review #'.$review->getKey(),
actionLabel: 'Open environment review',
url: $tenant instanceof ManagedEnvironment
? EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant)
? EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant)
: null,
freshnessAt: $review->generated_at,
),

View File

@ -4,6 +4,8 @@
namespace App\Support\Tenants;
use App\Support\Navigation\AdminSurfaceScope;
enum TenantInteractionLane: string
{
case StandardActiveOperating = 'standard_active_operating';
@ -11,16 +13,16 @@ enum TenantInteractionLane: string
case AdministrativeManagement = 'administrative_management';
case CanonicalWorkspaceRecord = 'canonical_workspace_record';
public static function fromPageCategory(TenantPageCategory $pageCategory): self
public static function fromSurfaceScope(AdminSurfaceScope $pageCategory): self
{
return match ($pageCategory) {
TenantPageCategory::OnboardingWorkflow => self::OnboardingWorkflow,
TenantPageCategory::TenantBound,
TenantPageCategory::TenantScopedEvidence => self::AdministrativeManagement,
TenantPageCategory::CanonicalWorkspaceRecordViewer => self::CanonicalWorkspaceRecord,
TenantPageCategory::WorkspaceWideSurface,
TenantPageCategory::WorkspaceScoped,
TenantPageCategory::WorkspaceChooserException => self::StandardActiveOperating,
AdminSurfaceScope::OnboardingWorkflow => self::OnboardingWorkflow,
AdminSurfaceScope::EnvironmentBound,
AdminSurfaceScope::EnvironmentScopedEvidence => self::AdministrativeManagement,
AdminSurfaceScope::CanonicalWorkspaceRecordViewer => self::CanonicalWorkspaceRecord,
AdminSurfaceScope::WorkspaceWideSurface,
AdminSurfaceScope::WorkspaceScoped,
AdminSurfaceScope::WorkspaceChooserException => self::StandardActiveOperating,
};
}
}

View File

@ -105,7 +105,7 @@ public function supportsQuestion(TenantOperabilityQuestion $question, TenantInte
return match ($question) {
TenantOperabilityQuestion::SelectorEligibility,
TenantOperabilityQuestion::RememberedContextValidity => $lane === TenantInteractionLane::StandardActiveOperating && $this->isSelectableInStandardLane(),
TenantOperabilityQuestion::TenantBoundViewability => $lane === TenantInteractionLane::AdministrativeManagement,
TenantOperabilityQuestion::EnvironmentBoundViewability => $lane === TenantInteractionLane::AdministrativeManagement,
TenantOperabilityQuestion::CanonicalLinkedRecordViewability => $lane === TenantInteractionLane::CanonicalWorkspaceRecord,
TenantOperabilityQuestion::ArchiveEligibility => $lane === TenantInteractionLane::AdministrativeManagement && $this->canArchive(),
TenantOperabilityQuestion::RestoreEligibility => $lane === TenantInteractionLane::AdministrativeManagement && $this->canRestore(),

View File

@ -100,7 +100,7 @@ public static function invalid(?string $normalizedValue = null): self
badgeIcon: 'heroicon-m-exclamation-triangle',
badgeIconColor: 'danger',
shortDescription: 'Lifecycle data is invalid and requires review.',
longDescription: 'The stored tenant lifecycle value is not canonical. Review the source data before treating this tenant as draft, onboarding, active, or archived.',
longDescription: 'The stored environment lifecycle value is not canonical. Review the source data before treating this tenant as draft, onboarding, active, or archived.',
isInvalidFallback: true,
lifecycle: null,
);

View File

@ -7,6 +7,7 @@
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\User;
use App\Support\Navigation\AdminSurfaceScope;
final readonly class TenantOperabilityContext
{
@ -15,7 +16,7 @@ public function __construct(
public ?User $actor,
public ?int $workspaceId,
public TenantInteractionLane $lane,
public ?TenantPageCategory $pageCategory = null,
public ?AdminSurfaceScope $pageCategory = null,
public ?string $linkedRecordType = null,
public ?int $linkedRecordId = null,
public ?ManagedEnvironmentOnboardingSession $onboardingDraft = null,
@ -28,7 +29,7 @@ public static function forTenant(
?User $actor = null,
?int $workspaceId = null,
TenantInteractionLane $lane = TenantInteractionLane::AdministrativeManagement,
?TenantPageCategory $pageCategory = null,
?AdminSurfaceScope $pageCategory = null,
?ManagedEnvironmentOnboardingSession $onboardingDraft = null,
?string $requiredCapability = null,
?ManagedEnvironment $selectedTenant = null,

View File

@ -8,7 +8,7 @@ enum TenantOperabilityQuestion: string
{
case SelectorEligibility = 'selector_eligibility';
case RememberedContextValidity = 'remembered_context_validity';
case TenantBoundViewability = 'tenant_bound_viewability';
case EnvironmentBoundViewability = 'environment_bound_viewability';
case CanonicalLinkedRecordViewability = 'canonical_linked_record_viewability';
case ArchiveEligibility = 'archive_eligibility';
case RestoreEligibility = 'restore_eligibility';

View File

@ -55,7 +55,7 @@ public function shortExplanation(): string
self::TenantAlreadyArchived => 'The tenant is already archived, so there is nothing else to do for this action.',
self::OnboardingNotResumable => 'This onboarding session can no longer be resumed from the current lifecycle state.',
self::CanonicalViewFollowupOnly => 'This canonical workspace view is informational only and cannot complete tenant follow-up directly.',
self::RememberedContextStale => 'The remembered tenant context is no longer valid for the current tenant selector state.',
self::RememberedContextStale => 'The remembered environment context is no longer valid for the current tenant selector state.',
self::WorkspaceClosed => 'This workspace is closed and cannot be used for active tenant context or new tenant operations until it is reopened.',
self::TenantRemovedFromWorkspace => 'This tenant was removed from the workspace and cannot be selected or used for new tenant operations until it is restored.',
};

View File

@ -5,20 +5,22 @@
namespace App\Support\Ui\GovernanceArtifactTruth;
use App\Filament\Resources\BaselineSnapshotResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\BaselineSnapshot;
use App\Models\EnvironmentReview;
use App\Models\EvidenceSnapshot;
use App\Models\FindingExceptionDecision;
use App\Models\OperationRun;
use App\Models\ReviewPack;
use App\Models\StoredReport;
use App\Models\EnvironmentReview;
use App\Services\Baselines\BaselineSnapshotTruthResolver;
use App\Services\Baselines\SnapshotRendering\FidelityState;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\EnvironmentReviewStatus;
use App\Support\Evidence\EvidenceCompletenessState;
use App\Support\OperationCatalog;
use App\Support\OperationRunLinks;
@ -28,8 +30,6 @@
use App\Support\ReasonTranslation\ReasonPresenter;
use App\Support\ReasonTranslation\ReasonResolutionEnvelope;
use App\Support\ReviewPackStatus;
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\EnvironmentReviewStatus;
use App\Support\Ui\DerivedState\DerivedStateFamily;
use App\Support\Ui\DerivedState\DerivedStateKey;
use App\Support\Ui\DerivedState\RequestScopedDerivedStateStore;
@ -600,7 +600,7 @@ private function buildEnvironmentReviewEnvelope(EnvironmentReview $review): Arti
if ($publishBlockers !== [] && $review->tenant !== null) {
$nextActionUrl = $this->panelSafeTenantArtifactUrl(
fn (): string => EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $review->tenant)
fn (): string => EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $review->tenant)
);
} elseif (($freshnessState === 'stale' || $contentState === 'partial') && $review->tenant !== null && $review->evidenceSnapshot !== null) {
$nextActionUrl = $this->panelSafeTenantArtifactUrl(
@ -642,7 +642,7 @@ private function buildEnvironmentReviewEnvelope(EnvironmentReview $review): Arti
relatedRunId: $review->operation_run_id !== null ? (int) $review->operation_run_id : null,
relatedArtifactUrl: $review->tenant !== null
? $this->panelSafeTenantArtifactUrl(
fn (): string => EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $review->tenant)
fn (): string => EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $review->tenant)
)
: null,
includePublicationDimension: true,
@ -785,7 +785,7 @@ private function buildReviewPackEnvelope(ReviewPack $pack): ArtifactTruthEnvelop
if ($sourceReview instanceof EnvironmentReview && $pack->tenant !== null) {
$nextActionUrl = $this->panelSafeTenantArtifactUrl(
fn (): string => EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $sourceReview], $pack->tenant)
fn (): string => EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $sourceReview], $pack->tenant)
);
} elseif (($freshnessState === 'stale' || $contentState === 'partial') && $pack->tenant !== null && $pack->evidenceSnapshot !== null) {
$nextActionUrl = $this->panelSafeTenantArtifactUrl(

View File

@ -7,6 +7,7 @@
use App\Filament\Resources\BackupScheduleResource;
use App\Filament\Resources\BackupSetResource;
use App\Filament\Resources\EntraGroupResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\FindingExceptionResource;
use App\Filament\Resources\FindingResource;
@ -15,10 +16,10 @@
use App\Filament\Resources\PolicyVersionResource;
use App\Filament\Resources\RestoreRunResource;
use App\Filament\Resources\StoredReportResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\BackupSchedule;
use App\Models\BackupSet;
use App\Models\EntraGroup;
use App\Models\EnvironmentReview;
use App\Models\EvidenceSnapshot;
use App\Models\Finding;
use App\Models\FindingException;
@ -27,7 +28,6 @@
use App\Models\PolicyVersion;
use App\Models\RestoreRun;
use App\Models\StoredReport;
use App\Models\EnvironmentReview;
final class TenantOwnedModelFamilies
{
@ -251,7 +251,7 @@ public static function scopeExceptions(): array
'why_excepted' => 'Workspace-admin tenant-default surface referencing tenant-owned data without being part of the mandatory first-slice canon.',
'still_required_checks' => [
'workspace membership',
'remembered tenant entitlement',
'remembered environment entitlement',
'capability gating on the destination action',
],
],

View File

@ -18,7 +18,7 @@ final class WorkspaceContext
public const INTENDED_URL_SESSION_KEY = 'workspace_intended_url';
public const LAST_TENANT_IDS_SESSION_KEY = 'workspace_last_tenant_ids';
public const LAST_ENVIRONMENT_IDS_SESSION_KEY = 'workspace_last_environment_ids';
public function __construct(
private WorkspaceResolver $resolver,
@ -55,7 +55,7 @@ public function currentWorkspace(?Request $request = null): ?Workspace
return $workspace;
}
public function currentWorkspaceOrTenantWorkspace(?ManagedEnvironment $tenant = null, ?Request $request = null): ?Workspace
public function currentWorkspaceOrEnvironmentWorkspace(?ManagedEnvironment $tenant = null, ?Request $request = null): ?Workspace
{
$workspace = $this->currentWorkspace($request);
@ -96,19 +96,19 @@ public function setCurrentWorkspace(Workspace $workspace, ?User $user = null, ?R
}
}
public function rememberLastTenantId(int $workspaceId, int $tenantId, ?Request $request = null): void
public function rememberLastEnvironmentId(int $workspaceId, int $tenantId, ?Request $request = null): void
{
$session = ($request && $request->hasSession()) ? $request->session() : session();
$map = $session->get(self::LAST_TENANT_IDS_SESSION_KEY, []);
$map = $session->get(self::LAST_ENVIRONMENT_IDS_SESSION_KEY, []);
$map = is_array($map) ? $map : [];
$map[(string) $workspaceId] = $tenantId;
$session->put(self::LAST_TENANT_IDS_SESSION_KEY, $map);
$session->put(self::LAST_ENVIRONMENT_IDS_SESSION_KEY, $map);
}
public function rememberTenantContext(ManagedEnvironment $tenant, ?Request $request = null): bool
public function rememberEnvironmentContext(ManagedEnvironment $tenant, ?Request $request = null): bool
{
$workspaceId = $this->currentWorkspaceId($request);
@ -125,23 +125,23 @@ public function rememberTenantContext(ManagedEnvironment $tenant, ?Request $requ
);
if (! $outcome->allowed) {
$this->clearLastTenantId($request);
$this->clearLastEnvironmentId($request);
return false;
}
if (! $this->userCanAccessTenant($tenant, $request)) {
$this->clearRememberedTenantContext($request);
$this->clearRememberedEnvironmentContext($request);
return false;
}
$this->rememberLastTenantId($workspaceId, (int) $tenant->getKey(), $request);
$this->rememberLastEnvironmentId($workspaceId, (int) $tenant->getKey(), $request);
return true;
}
public function lastTenantId(?Request $request = null): ?int
public function lastEnvironmentId(?Request $request = null): ?int
{
$workspaceId = $this->currentWorkspaceId($request);
@ -151,7 +151,7 @@ public function lastTenantId(?Request $request = null): ?int
$session = ($request && $request->hasSession()) ? $request->session() : session();
$map = $session->get(self::LAST_TENANT_IDS_SESSION_KEY, []);
$map = $session->get(self::LAST_ENVIRONMENT_IDS_SESSION_KEY, []);
$map = is_array($map) ? $map : [];
$id = $map[(string) $workspaceId] ?? null;
@ -159,7 +159,7 @@ public function lastTenantId(?Request $request = null): ?int
return is_int($id) ? $id : (is_numeric($id) ? (int) $id : null);
}
public function clearLastTenantId(?Request $request = null): void
public function clearLastEnvironmentId(?Request $request = null): void
{
$workspaceId = $this->currentWorkspaceId($request);
@ -169,20 +169,20 @@ public function clearLastTenantId(?Request $request = null): void
$session = ($request && $request->hasSession()) ? $request->session() : session();
$map = $session->get(self::LAST_TENANT_IDS_SESSION_KEY, []);
$map = $session->get(self::LAST_ENVIRONMENT_IDS_SESSION_KEY, []);
$map = is_array($map) ? $map : [];
unset($map[(string) $workspaceId]);
$session->put(self::LAST_TENANT_IDS_SESSION_KEY, $map);
$session->put(self::LAST_ENVIRONMENT_IDS_SESSION_KEY, $map);
}
public function clearRememberedTenantContext(?Request $request = null): void
public function clearRememberedEnvironmentContext(?Request $request = null): void
{
$this->clearLastTenantId($request);
$this->clearLastEnvironmentId($request);
}
public function rememberedTenant(?Request $request = null): ?ManagedEnvironment
public function rememberedEnvironment(?Request $request = null): ?ManagedEnvironment
{
$workspaceId = $this->currentWorkspaceId($request);
@ -190,31 +190,31 @@ public function rememberedTenant(?Request $request = null): ?ManagedEnvironment
return null;
}
$rememberedTenantId = $this->lastTenantId($request);
$rememberedEnvironmentId = $this->lastEnvironmentId($request);
if ($rememberedTenantId === null) {
if ($rememberedEnvironmentId === null) {
return null;
}
$tenant = ManagedEnvironment::query()
->withTrashed()
->whereKey($rememberedTenantId)
->whereKey($rememberedEnvironmentId)
->first();
if (! $tenant instanceof ManagedEnvironment) {
$this->clearRememberedTenantContext($request);
$this->clearRememberedEnvironmentContext($request);
return null;
}
if ((int) $tenant->workspace_id !== $workspaceId) {
$this->clearRememberedTenantContext($request);
$this->clearRememberedEnvironmentContext($request);
return null;
}
if (! $this->userCanAccessTenant($tenant, $request)) {
$this->clearRememberedTenantContext($request);
$this->clearRememberedEnvironmentContext($request);
return null;
}
@ -228,7 +228,7 @@ public function rememberedTenant(?Request $request = null): ?ManagedEnvironment
);
if (! $outcome->allowed) {
$this->clearRememberedTenantContext($request);
$this->clearRememberedEnvironmentContext($request);
return null;
}

View File

@ -1,12 +1,11 @@
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use App\Http\Middleware\ApplyResolvedLocale;
use App\Http\Middleware\SuppressDebugbarForSmokeRequests;
use App\Http\Middleware\UseSystemSessionCookieForLivewireRequests;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
@ -35,7 +34,7 @@
'ensure-platform-capability' => \App\Http\Middleware\EnsurePlatformCapability::class,
'ensure-workspace-member' => \App\Http\Middleware\EnsureWorkspaceMember::class,
'ensure-workspace-selected' => \App\Http\Middleware\EnsureWorkspaceSelected::class,
'ensure-filament-tenant-selected' => \App\Support\Middleware\EnsureFilamentTenantSelected::class,
'ensure-environment-context-selected' => \App\Support\Middleware\EnsureEnvironmentContextSelected::class,
]);
$middleware->prependToPriorityList(

View File

@ -15,32 +15,32 @@
$user = auth()->user();
$tenants = collect();
$environments = collect();
if ($user instanceof User && $workspace) {
$tenants = collect($user->getTenants(Filament::getCurrentOrDefaultPanel()))
->filter(fn ($tenant): bool => $tenant instanceof ManagedEnvironment && (int) $tenant->workspace_id === (int) $workspace->getKey())
$environments = collect($user->getTenants(Filament::getCurrentOrDefaultPanel()))
->filter(fn ($environment): bool => $environment instanceof ManagedEnvironment && (int) $environment->workspace_id === (int) $workspace->getKey())
->values();
}
$currentTenant = $resolvedContext->tenant;
$currentTenantId = $currentTenant instanceof ManagedEnvironment ? (int) $currentTenant->getKey() : null;
$currentTenantName = $currentTenant instanceof ManagedEnvironment ? $currentTenant->getFilamentName() : null;
$currentEnvironment = $resolvedContext->tenant;
$currentEnvironmentId = $currentEnvironment instanceof ManagedEnvironment ? (int) $currentEnvironment->getKey() : null;
$currentEnvironmentName = $currentEnvironment instanceof ManagedEnvironment ? $currentEnvironment->getFilamentName() : null;
$lastTenantId = $workspaceContext->lastTenantId(request());
$canClearEnvironmentContext = $currentTenant instanceof ManagedEnvironment || $lastTenantId !== null;
$lastEnvironmentId = $workspaceContext->lastEnvironmentId(request());
$canClearEnvironmentContext = $currentEnvironment instanceof ManagedEnvironment || $lastEnvironmentId !== null;
@endphp
@php
$tenantLabel = $currentTenantName ?? __('localization.shell.no_environment_selected');
$environmentLabel = $currentEnvironmentName ?? __('localization.shell.no_environment_selected');
$workspaceLabel = $workspace?->name ?? __('localization.shell.choose_workspace');
$hasActiveTenant = $currentTenantName !== null;
$hasActiveEnvironment = $currentEnvironmentName !== null;
$managedEnvironmentsUrl = $workspace
? route('admin.workspace.managed-environments.index', ['workspace' => $workspace])
: route('admin.onboarding');
$workspaceUrl = $workspace
? route('admin.home')
: ChooseWorkspace::getUrl(panel: 'admin');
$tenantTriggerLabel = $workspace ? $tenantLabel : __('localization.shell.choose_workspace');
$environmentTriggerLabel = $workspace ? $environmentLabel : __('localization.shell.choose_workspace');
$localePlane = 'admin';
@endphp
@ -59,7 +59,7 @@ class="inline-flex items-center gap-1.5 rounded-l-lg px-2.5 py-1.5 font-medium t
<x-filament::icon icon="heroicon-m-chevron-right" class="h-3 w-3 shrink-0 text-gray-300 dark:text-gray-600" />
@endif
{{-- Dropdown trigger: tenant label + chevron --}}
{{-- Dropdown trigger: environment label + chevron --}}
<x-filament::dropdown placement="bottom-start" teleport width="xs">
<x-slot name="trigger">
<button
@ -67,8 +67,8 @@ class="inline-flex items-center gap-1.5 rounded-l-lg px-2.5 py-1.5 font-medium t
aria-label="{{ $workspace ? __('localization.shell.environment_scope') : __('localization.shell.select_environment') }}"
class="inline-flex items-center gap-1.5 rounded-r-lg px-2 py-1.5 transition hover:bg-gray-50 dark:hover:bg-white/10"
>
<span class="{{ $workspace && $hasActiveTenant ? 'font-medium text-primary-600 dark:text-primary-400' : 'text-gray-500 dark:text-gray-400' }}">
{{ $tenantTriggerLabel }}
<span class="{{ $workspace && $hasActiveEnvironment ? 'font-medium text-primary-600 dark:text-primary-400' : 'text-gray-500 dark:text-gray-400' }}">
{{ $environmentTriggerLabel }}
</span>
<x-filament::icon icon="heroicon-m-chevron-down" class="h-3.5 w-3.5 text-gray-400 dark:text-gray-500" />
@ -121,7 +121,7 @@ class="flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-gray-700 transi
@if ($workspace)
<div class="border-t border-gray-200 dark:border-white/10"></div>
{{-- ManagedEnvironment section --}}
{{-- Managed Environment section --}}
<div class="space-y-2">
<div class="flex items-center justify-between">
<div class="text-xs font-semibold uppercase tracking-wider text-gray-400 dark:text-gray-500">
@ -129,11 +129,11 @@ class="flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-gray-700 transi
</div>
</div>
@if ($resolvedContext->pageCategory->requiresExplicitTenant() && $hasActiveTenant)
@if ($resolvedContext->pageCategory->requiresExplicitEnvironment() && $hasActiveEnvironment)
<div class="space-y-2">
<div class="flex items-center gap-2 rounded-lg bg-primary-50 px-3 py-2 dark:bg-primary-950/30">
<x-filament::icon icon="heroicon-o-building-office-2" class="h-4 w-4 text-primary-600 dark:text-primary-400" />
<span class="text-sm font-medium text-primary-700 dark:text-primary-300">{{ $currentTenantName }}</span>
<span class="text-sm font-medium text-primary-700 dark:text-primary-300">{{ $currentEnvironmentName }}</span>
<a
href="{{ ChooseEnvironment::getUrl(panel: 'admin') }}"
class="ml-auto text-xs font-medium text-primary-600 hover:text-primary-500 dark:text-primary-400 dark:hover:text-primary-300"
@ -153,7 +153,7 @@ class="ml-auto text-xs font-medium text-primary-600 hover:text-primary-500 dark:
@endif
</div>
@else
@if ($tenants->isEmpty())
@if ($environments->isEmpty())
<div class="space-y-2 rounded-lg border border-dashed border-gray-300 px-3 py-3 text-center text-xs text-gray-500 dark:border-gray-600 dark:text-gray-400">
<div>{{ __('localization.shell.no_active_environments') }}</div>
<a href="{{ $managedEnvironmentsUrl }}" class="inline-flex items-center gap-1 text-primary-600 hover:text-primary-500 dark:text-primary-400 dark:hover:text-primary-300">
@ -162,7 +162,7 @@ class="ml-auto text-xs font-medium text-primary-600 hover:text-primary-500 dark:
</a>
</div>
@else
@if (! $hasActiveTenant)
@if (! $hasActiveEnvironment)
<div class="rounded-lg bg-gray-50 px-3 py-2 text-xs text-gray-600 dark:bg-white/5 dark:text-gray-400">
{{ __('localization.shell.workspace_wide_available_without_environment') }}
</div>
@ -176,19 +176,19 @@ class="fi-input fi-text-input w-full"
/>
<div class="max-h-48 overflow-auto rounded-lg border border-gray-200 dark:border-gray-700">
@foreach ($tenants as $tenant)
@foreach ($environments as $environment)
@php
$isActive = $currentTenantId !== null && (int) $tenant->getKey() === $currentTenantId;
$isActive = $currentEnvironmentId !== null && (int) $environment->getKey() === $currentEnvironmentId;
@endphp
<form method="POST" action="{{ route('admin.select-environment') }}">
@csrf
<input type="hidden" name="managed_environment_id" value="{{ (int) $tenant->getKey() }}" />
<input type="hidden" name="managed_environment_id" value="{{ (int) $environment->getKey() }}" />
<button
type="submit"
class="flex w-full items-center gap-2 px-3 py-2 text-left text-sm transition {{ $isActive ? 'bg-primary-50 font-medium text-primary-700 dark:bg-primary-950/30 dark:text-primary-300' : 'text-gray-700 hover:bg-gray-50 dark:text-gray-300 dark:hover:bg-white/5' }}"
data-search="{{ (string) str($tenant->getFilamentName())->lower() }}"
data-search="{{ (string) str($environment->getFilamentName())->lower() }}"
x-show="query === '' || ($el.dataset.search ?? '').includes(query.toLowerCase())"
>
@if ($isActive)
@ -197,7 +197,7 @@ class="flex w-full items-center gap-2 px-3 py-2 text-left text-sm transition {{
<x-filament::icon icon="heroicon-o-building-office-2" class="h-4 w-4 shrink-0 text-gray-400 dark:text-gray-500" />
@endif
{{ $tenant->getFilamentName() }}
{{ $environment->getFilamentName() }}
</button>
</form>
@endforeach

View File

@ -5,24 +5,23 @@
use App\Http\Controllers\Auth\EntraController;
use App\Http\Controllers\ClearEnvironmentContextController;
use App\Http\Controllers\LocalizationController;
use App\Http\Controllers\ManagedEnvironmentOnboardingController;
use App\Http\Controllers\OpenFindingExceptionsQueueController;
use App\Http\Controllers\RbacDelegatedAuthController;
use App\Http\Controllers\ReviewPackDownloadController;
use App\Http\Controllers\SelectEnvironmentController;
use App\Http\Controllers\SwitchWorkspaceController;
use App\Http\Controllers\ManagedEnvironmentOnboardingController;
use App\Http\Middleware\SuppressDebugbarForSmokeRequests;
use App\Models\ProviderConnection;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Onboarding\OnboardingDraftResolver;
use App\Services\Tenants\TenantOperabilityService;
use App\Support\Auth\WorkspaceRole;
use App\Support\ManagedEnvironmentLinks;
use App\Services\Tenants\TenantOperabilityService;
use App\Support\Navigation\AdminSurfaceScope;
use App\Support\Tenants\TenantOperabilityQuestion;
use App\Support\Tenants\TenantPageCategory;
use App\Support\Workspaces\WorkspaceContext;
use App\Support\Workspaces\WorkspaceResolver;
use Filament\Http\Middleware\Authenticate as FilamentAuthenticate;
@ -268,7 +267,7 @@
$workspaceContext->setCurrentWorkspace($workspace, $user, $request);
if ($tenant instanceof ManagedEnvironment) {
$workspaceContext->rememberTenantContext($tenant, $request);
$workspaceContext->rememberEnvironmentContext($tenant, $request);
} else {
$workspaceContext->clearRememberedTenantContext($request);
}
@ -377,10 +376,10 @@
$allowed = app(TenantOperabilityService::class)->outcomeFor(
tenant: $tenant,
question: TenantOperabilityQuestion::TenantBoundViewability,
question: TenantOperabilityQuestion::EnvironmentBoundViewability,
actor: $user,
workspaceId: $workspaceId,
lane: TenantPageCategory::TenantBound->lane(),
lane: AdminSurfaceScope::EnvironmentBound->lane(),
)->allowed;
abort_unless($allowed, 404);
@ -394,7 +393,7 @@
DispatchServingFilamentEvent::class,
FilamentAuthenticate::class,
'ensure-workspace-member',
'ensure-filament-tenant-selected',
'ensure-environment-context-selected',
])
->prefix('/admin/workspaces/{workspace}')
->group(function (): void {
@ -470,7 +469,7 @@
DispatchServingFilamentEvent::class,
FilamentAuthenticate::class,
'ensure-workspace-selected',
'ensure-filament-tenant-selected',
'ensure-environment-context-selected',
])
->get('/admin/audit-log', \App\Filament\Pages\Monitoring\AuditLog::class)
->name('admin.monitoring.audit-log');
@ -507,7 +506,7 @@
DispatchServingFilamentEvent::class,
FilamentAuthenticate::class,
'ensure-workspace-member',
'ensure-filament-tenant-selected',
'ensure-environment-context-selected',
])
->get('/admin/workspaces/{workspace}/environments/{environment:slug}', \App\Filament\Pages\EnvironmentDashboard::class)
->name('admin.workspace.environments.show');
@ -520,7 +519,7 @@
DispatchServingFilamentEvent::class,
FilamentAuthenticate::class,
'ensure-workspace-member',
'ensure-filament-tenant-selected',
'ensure-environment-context-selected',
])
->get('/admin/workspaces/{workspace}/environments/{environment:slug}/diagnostics', \App\Filament\Pages\EnvironmentDiagnostics::class)
->name('admin.workspace.environments.diagnostics');
@ -533,7 +532,7 @@
DispatchServingFilamentEvent::class,
FilamentAuthenticate::class,
'ensure-workspace-member',
'ensure-filament-tenant-selected',
'ensure-environment-context-selected',
])
->get('/admin/workspaces/{workspace}/environments/{environment:slug}/access-scopes', \App\Filament\Resources\ManagedEnvironmentResource\Pages\ManageEnvironmentAccessScopes::class)
->name('admin.workspace.environments.access-scopes');

View File

@ -59,7 +59,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
],
]);

View File

@ -72,12 +72,12 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenantPublished->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenantPublished->workspace_id => (int) $tenantPublished->getKey(),
],
]);
visit(EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $publishedReview], $tenantPublished))
visit(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $publishedReview], $tenantPublished))
->waitForText('Verwandter Kontext')
->assertSee('Kunden-Workspace öffnen')
->assertNoJavaScriptErrors()

View File

@ -2,9 +2,9 @@
declare(strict_types=1);
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\ManagedEnvironment;
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\EnvironmentReviewStatus;
@ -90,7 +90,7 @@
->assertSee('Stale')
->assertSee('Refresh the stale evidence before relying on this snapshot');
visit(EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $partialReview], $partialTenant))
visit(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $partialReview], $partialTenant))
->waitForText('Outcome summary')
->assertNoJavaScriptErrors()
->assertSee('Internal only')

View File

@ -38,7 +38,7 @@
$this->actingAs($fixture['user'])->withSession([
WorkspaceContext::SESSION_KEY => (int) $fixture['workspace']->getKey(),
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $fixture['workspace']->getKey() => (int) $fixture['visibleTenant']->getKey(),
],
]);
@ -97,7 +97,7 @@
$this->actingAs($viewer)->withSession([
WorkspaceContext::SESSION_KEY => (int) $fixture['workspace']->getKey(),
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $fixture['workspace']->getKey() => (int) $fixture['visibleTenant']->getKey(),
],
]);
@ -134,7 +134,7 @@
$this->actingAs($fixture['user'])->withSession([
WorkspaceContext::SESSION_KEY => (int) $fixture['workspace']->getKey(),
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $fixture['workspace']->getKey() => (int) $fixture['visibleTenant']->getKey(),
],
]);

View File

@ -6,12 +6,12 @@
use App\Filament\Resources\BackupSetResource;
use App\Filament\Resources\BaselineProfileResource;
use App\Filament\Resources\BaselineSnapshotResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\FindingExceptionResource;
use App\Filament\Resources\ManagedEnvironmentResource;
use App\Filament\Resources\PolicyVersionResource;
use App\Filament\Resources\ReviewPackResource;
use App\Filament\Resources\ManagedEnvironmentResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\Workspaces\WorkspaceResource;
use App\Models\AlertDestination;
use App\Models\BackupSet;
@ -20,11 +20,11 @@
use App\Models\BaselineSnapshotItem;
use App\Models\EvidenceSnapshot;
use App\Models\Finding;
use App\Models\ManagedEnvironment;
use App\Models\OperationRun;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Services\Findings\FindingExceptionService;
use App\Support\Evidence\EvidenceCompletenessState;
@ -157,7 +157,7 @@ function spec192ApprovedFindingException(ManagedEnvironment $tenant, User $reque
->assertSee('Open finding')
->assertSee('Renew exception');
visit(EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant))
visit(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant))
->waitForText('Related context')
->assertNoJavaScriptErrors()
->assertScript("document.querySelectorAll('[data-supporting-group-kind]').length === 0", true)

View File

@ -3,10 +3,10 @@
declare(strict_types=1);
use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\FindingExceptionResource;
use App\Filament\Resources\ManagedEnvironmentResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\EvidenceSnapshot;
use App\Models\Finding;
use App\Models\FindingException;
@ -17,13 +17,13 @@
use App\Models\User;
use App\Services\Findings\FindingExceptionService;
use App\Support\Auth\PlatformCapabilities;
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\EnvironmentReviewStatus;
use App\Support\Evidence\EvidenceCompletenessState;
use App\Support\Evidence\EvidenceSnapshotStatus;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\System\SystemOperationRunLinks;
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\EnvironmentReviewStatus;
use Illuminate\Foundation\Testing\RefreshDatabase;
pest()->browser()->timeout(20_000);
@ -194,7 +194,7 @@ function spec194RelativeRedirect(string $redirect): string
->assertSee('Renew exception')
->assertSee('Revoke exception');
visit(EnvironmentReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant))
visit(EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $review], $tenant))
->waitForText('Related context')
->assertNoJavaScriptErrors()
->assertNoConsoleLogs()

View File

@ -88,7 +88,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
],
]);
@ -154,7 +154,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
],
]);

View File

@ -36,7 +36,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
],
]);

View File

@ -51,7 +51,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
],
]);

View File

@ -15,7 +15,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
],
]);

View File

@ -2,11 +2,11 @@
declare(strict_types=1);
use App\Filament\Resources\EnvironmentReviewResource;
use App\Filament\Resources\EvidenceSnapshotResource;
use App\Filament\Resources\FindingResource;
use App\Filament\Resources\InventoryItemResource;
use App\Filament\Resources\StoredReportResource;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Models\Finding;
use App\Models\InventoryItem;
use App\Models\StoredReport;
@ -41,7 +41,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
],
]);

View File

@ -50,7 +50,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $workspace->getKey(),
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $workspace->getKey() => (int) $environment->getKey(),
],
]);

View File

@ -20,13 +20,13 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
],
]);
session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [
session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
(string) $tenant->workspace_id => (int) $tenant->getKey(),
]);

View File

@ -48,7 +48,7 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id,
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $environment->workspace_id => (int) $environment->getKey(),
],
]);

View File

@ -24,13 +24,13 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $workspace->getKey(),
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $workspace->getKey() => (int) $environment->getKey(),
],
]);
session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());
session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [
session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
(string) $workspace->getKey() => (int) $environment->getKey(),
]);

View File

@ -32,13 +32,13 @@
$this->actingAs($user)->withSession([
WorkspaceContext::SESSION_KEY => (int) $workspace->getKey(),
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $workspace->getKey() => (int) $environmentA->getKey(),
],
]);
session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());
session()->put(WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY, [
session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
(string) $workspace->getKey() => (int) $environmentA->getKey(),
]);
@ -77,7 +77,7 @@
'wide_text' => $environmentB->name,
],
'customer review workspace' => [
'filtered_url' => CustomerReviewWorkspace::tenantPrefilterUrl($environmentA),
'filtered_url' => CustomerReviewWorkspace::environmentFilterUrl($environmentA),
'clean_url' => CustomerReviewWorkspace::getUrl(panel: 'admin'),
'wide_text' => $environmentB->name,
],
@ -148,7 +148,7 @@
FindingExceptionsQueue::getUrl(panel: 'admin', parameters: [
'environment_id' => (int) $environmentA->getKey(),
]),
CustomerReviewWorkspace::tenantPrefilterUrl($environmentA),
CustomerReviewWorkspace::environmentFilterUrl($environmentA),
route('admin.evidence.overview', [
'environment_id' => (int) $environmentA->getKey(),
]),

Some files were not shown because too many files have changed in this diff Show More