feat: sentry-laravel install + scrubber + ignored exceptions
WS-7 PR-2 commit 1. Wires sentry-laravel into the app behind a config-only no-op when SENTRY_DSN_BACKEND is empty (RFC §3.3). - composer require sentry/sentry-laravel ^4.15 (resolved 4.25.1) - config/sentry.php: DSN env mapped to SENTRY_DSN_BACKEND, environment falls back to APP_ENV, traces/profiles forced to 0.0 (RFC §2 amendment B), send_default_pii hard-pinned false, before_send to SentryEventScrubber, ignore_exceptions covers ValidationException / AuthenticationException / AuthorizationException. - app/Services/Observability/SentryEventScrubber.php: recursive body / header / query-string scrubber + form_values wholesale replacement + HttpException sub-500 drop (status filter that ignore_exceptions cannot do class-only). Max-depth guard against malicious payloads. - app/Enums/Observability/ActorType.php: enum + resolver for §3.6 actor_type tag (consumed by BindSentryContext in commit 2). - tests/Feature/Observability/PiiScrubbingTest.php: 20 cases. - api/.env.example: SENTRY_DSN_BACKEND + SENTRY_RELEASE entries. Larastan: clean. Test count: 1487 to 1507. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
55
api/app/Enums/Observability/ActorType.php
Normal file
55
api/app/Enums/Observability/ActorType.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Enums\Observability;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Actor classification used as the `actor_type` Sentry tag (RFC-WS-7 §3.6).
|
||||
*
|
||||
* Resolution precedence (most specific first):
|
||||
* 1. Portal-token request → PORTAL_TOKEN
|
||||
* 2. Authenticated super_admin → SUPER_ADMIN
|
||||
* 3. Authenticated org_admin → ORGANIZER_ADMIN
|
||||
* 4. Authenticated volunteer (role match) → VOLUNTEER
|
||||
* 5. Other authenticated user → ORG_MEMBER
|
||||
* 6. None of the above → UNAUTHENTICATED
|
||||
*/
|
||||
enum ActorType: string
|
||||
{
|
||||
case ORGANIZER_ADMIN = 'organizer_admin';
|
||||
case SUPER_ADMIN = 'super_admin';
|
||||
case PORTAL_TOKEN = 'portal_token';
|
||||
case VOLUNTEER = 'volunteer';
|
||||
case ORG_MEMBER = 'org_member';
|
||||
case UNAUTHENTICATED = 'unauthenticated';
|
||||
|
||||
public static function resolve(?Authenticatable $user, ?Request $request): self
|
||||
{
|
||||
if ($request !== null && $request->attributes->get('portal_context') !== null) {
|
||||
return self::PORTAL_TOKEN;
|
||||
}
|
||||
|
||||
if (! $user instanceof User) {
|
||||
return self::UNAUTHENTICATED;
|
||||
}
|
||||
|
||||
if ($user->hasRole('super_admin')) {
|
||||
return self::SUPER_ADMIN;
|
||||
}
|
||||
|
||||
if ($user->hasRole('org_admin')) {
|
||||
return self::ORGANIZER_ADMIN;
|
||||
}
|
||||
|
||||
if ($user->hasRole('volunteer')) {
|
||||
return self::VOLUNTEER;
|
||||
}
|
||||
|
||||
return self::ORG_MEMBER;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user