withRouting( web: __DIR__.'/../routes/web.php', api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { $middleware->encryptCookies(except: ['appearance', 'sidebar_state', EnsureSimulationRecoveryCookie::NAME]); $middleware->web(append: [ PortalProfileSession::class, ProtectPrivilegedIdentity::class, AuditProfileDecision::class, ProtectProfileOpportunity::class, HandleAppearance::class, HandleInertiaRequests::class, PreserveFormFeedback::class, AddLinkHeadersForPreloadedAssets::class, ]); }) ->withExceptions(function (Exceptions $exceptions): void { $exceptions->dontReportWhen(fn (Throwable $exception) => $exception instanceof DecryptException && request()->isMethod('POST') && request()->is('two-factor-challenge')); $exceptions->render(function (DecryptException $exception, Request $request) { if (! $request->isMethod('POST') || ! $request->is('two-factor-challenge')) { return null; } $reference = (string) Str::uuid(); Log::warning('Two-factor credential could not be decrypted; authentication refused.', [ 'reference' => $reference, 'pending_user_id' => $request->session()->get('login.id'), ]); $request->session()->invalidate(); $request->session()->regenerateToken(); $message = 'Não foi possível verificar a autenticação desta conta. Inicie sessão novamente ou contacte o suporte.'; if ($request->expectsJson()) { $field = $request->filled('recovery_code') ? 'recovery_code' : 'code'; return response()->json(['message' => $message, 'errors' => [$field => [$message]], 'reference' => $reference], 422) ->header('Cache-Control', 'no-store'); } return redirect()->route('login')->withErrors(['email' => $message])->header('Cache-Control', 'no-store'); }); $exceptions->shouldRenderJsonWhen( fn (Request $request) => $request->is('api/*') || $request->expectsJson(), ); $exceptions->respond(function (Response $response, Throwable $exception, Request $request): Response { if ($request->is('api/*')) { $response->headers->set( 'X-Correlation-ID', (string) ($request->attributes->get('correlation_id') ?? (Str::isUuid($request->header('X-Correlation-ID')) ? $request->header('X-Correlation-ID') : Str::uuid())), ); } if (($exception instanceof QueryException || $exception instanceof PDOException) && ! $request->is('api/v1/simulation-drafts*')) { $reference = (string) ($response->headers->get('X-Correlation-ID') ?? $request->attributes->get('correlation_id') ?? Str::uuid()); $response->setStatusCode(503); $response->headers->set('Cache-Control', 'no-store'); if ($request->is('api/*') || $request->expectsJson()) { $response->setContent(json_encode([ 'message' => 'Serviço temporariamente indisponível. Tente novamente mais tarde.', 'reference' => $reference, ], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR)); $response->headers->set('Content-Type', 'application/json; charset=utf-8'); } else { $response->setContent(view('errors.database-unavailable', ['reference' => $reference])->render()); $response->headers->set('Content-Type', 'text/html; charset=utf-8'); } } if ($request->is('api/v1/simulation-drafts*') && $response->isServerError()) { $response->setContent(json_encode([ 'message' => 'Não foi possível guardar ou recuperar o rascunho. Os dados existentes não foram apagados. Tente novamente mais tarde.', 'reference' => $response->headers->get('X-Correlation-ID'), ], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR)); $response->headers->set('Content-Type', 'application/json; charset=utf-8'); } return $response; }); })->create(); (require __DIR__.'/storage.php')($app->basePath(), $app->storagePath()); return $app;