Secure Uploads - v1.0.0

Events

Four events fire across the upload lifecycle. All four use Laravel's class-based event syntax — listen via Event::listen() or EventServiceProvider::$listen.

Event When it fires Payload
FileUploaded After validation, scan, and storage all succeed SecureUploadedFile $file, RequestContext $context
FileUploadRejected When validation fails UploadedFile $file, ValidationResult $result, RequestContext $context
MalwareDetected When a scan returns infected = true SecureUploadedFile|UploadedFile $file, ScanResult $scanResult, RequestContext $context
FileServed When a signed-URL request hits SecureFileController::show() or download() SecureUploadedFile $file, Request $request

Listening

use ArtisanPackUI\SecureUploads\Events\MalwareDetected;
use Illuminate\Support\Facades\Event;

Event::listen(MalwareDetected::class, function (MalwareDetected $event) {
    logger()->critical('Malware detected', [
        'filename' => $event->file->original_filename,
        'signature' => $event->scanResult->signature,
        'ip' => $event->context->ipAddress,
    ]);
});

Or in EventServiceProvider:

protected $listen = [
    MalwareDetected::class => [
        AlertSecurityTeam::class,
        QuarantineUploaderAccount::class,
    ],
    FileUploaded::class => [
        AuditFileUpload::class,
    ],
];

Use cases

Audit logging. artisanpack-ui/security-analytics subscribes to all four events for the unified security audit trail. Listen for FileUploaded and FileServed to build your own access logs.

Threat response. Listen for MalwareDetected to alert (PagerDuty, Slack), quarantine the uploader account, or revoke active sessions.

Storage cleanup. Listen for FileUploadRejected to immediately purge any partial uploads — though the package handles this internally for the common cases.

Usage analytics. Aggregate FileUploaded payloads to compute storage usage per user / per model type for billing or quota enforcement.

RequestContext

RequestContext is a value object that captures everything relevant about the request that triggered the upload:

$context->ipAddress;     // string
$context->userAgent;     // ?string
$context->userId;        // ?int — authenticated user, if any
$context->sessionId;     // ?string
$context->referer;       // ?string
$context->routeName;     // ?string

It's built from the current Illuminate\Http\Request at the moment of attachment, so listeners get the full request context without having to re-derive it.