operationRun = $operationRun; } /** * @return array */ public function middleware(): array { return [new TrackOperationRun]; } public function handle( TenantPermissionService $permissions, OperationRunService $runs, TenantOnboardingAuditService $audit, ): void { $tenant = Tenant::query()->find($this->tenantId); if (! $tenant instanceof Tenant) { throw new RuntimeException('Tenant not found.'); } $user = User::query()->find($this->userId); if (! $user instanceof User) { throw new RuntimeException('User not found.'); } $result = $permissions->compare( tenant: $tenant, grantedStatuses: null, persist: true, liveCheck: true, useConfiguredStub: false, ); $overall = (string) ($result['overall_status'] ?? 'error'); $tenant->forceFill([ 'rbac_last_checked_at' => now(), 'rbac_last_warnings' => $overall === 'granted' ? [] : ['permissions_not_granted'], ])->save(); if (! $this->operationRun instanceof OperationRun) { return; } if ($overall === 'granted') { $runs->updateRun( $this->operationRun, status: OperationRunStatus::Completed->value, outcome: OperationRunOutcome::Succeeded->value, ); $tenant->forceFill([ 'onboarding_status' => 'completed', 'onboarding_completed_at' => now(), ])->save(); TenantOnboardingSession::query() ->where('tenant_id', $tenant->getKey()) ->where('status', 'active') ->update([ 'status' => 'completed', 'current_step' => 'verification', 'completed_at' => now(), ]); $audit->onboardingCompleted( tenant: $tenant, actor: $user, context: [ 'operation_run_id' => (int) $this->operationRun->getKey(), ], ); return; } $runs->updateRun( $this->operationRun, status: OperationRunStatus::Completed->value, outcome: OperationRunOutcome::Failed->value, failures: [[ 'code' => 'tenant.rbac.verify.not_granted', 'message' => 'Permissions are missing or could not be verified.', ]], ); } }