finity-labs/fin-sentinel
Fin Sentinel is a Laravel package for application monitoring, auditing, and alerting. It helps you track important events, spot suspicious or failing behavior, and respond before users are affected, with a lightweight setup that fits naturally into existing Laravel applications.
^1.2.3 (composer require finity-labs/fin-sentinel:^1.2.3) before doing anything else. This is a patch release, but it changes authorization behaviour for an existing route, so treat it as a security upgrade rather than a routine bump.src/Pages/LogFileViewer.php. It should now carry HasPageShieldSupport and no longer rely on the route being merely "signed-in". The list page (LogFileList) is the reference implementation; the viewer now behaves the same way./{panel}/sentinel/logs/{base64 name} (e.g. laravel.log → base64). On 1.2.3 this should 403 until the role is granted access. Then grant View:LogFileViewer and confirm it opens.shield:generate discovers the page from the panel, and the install command names it), so there is nothing to regenerate — you only need to assign View:LogFileViewer to the roles that previously relied on the viewer being unprotected.page_LogFileViewer Gate ability in a service provider, or rely on the plugin's canAccess() closure. If you do neither, the plugin closure is the only control — make sure it is set.View:LogFileViewer wherever View:LogFileList is granted. These are separate page permissions; granting only the list permission now leaves file opening broken for that role.View:LogFileViewer) → host-defined page_LogFileViewer Gate → plugin canAccess() closure. Pick one layer per environment. Mixing Shield and a custom Gate in the same app makes it non-obvious which rule wins; the trait's resolution order is what matters.canAccess() closure for "is this whole log feature enabled for this panel/user?" and the page permission for "may this role read log contents?". Do not put per-file logic in the closure — the path check in mount() is unchanged and handles the file selection, not authorization.tests/PanelTestCase.php bound to tests/Feature/Pages, which is the pattern to copy: boot a real Filament panel, then assert 200 for a permitted user and 403 for a denied one against both the list and the viewer routes. Remember the route parameter is a base64-encoded filename.View:LogFileList but without View:LogFileViewer gets a 403 on /{panel}/sentinel/logs/{base64('laravel.log')}. That single test is what would have caught the v1.2.2 behaviour.super_admin typically short-circuits via Gate::before. Verify that path still opens the viewer; a Gate::before returning true will bypass the page permission, which is usually desired but should be a conscious decision.View:LogFileViewer will start receiving 403s the moment you deploy. Audit roles and seed permissions before rolling out, or you will field "the log viewer is broken" reports.<=1.2.2 the viewer had no permission check at all — any signed-in panel user who could guess a filename could read logs. Filenames like laravel.log are trivially guessable and base64 is encoding, not security. Rotate anything sensitive that may have been written to logs (tokens, credentials, PII) and check access logs for the sentinel/logs/ route.View:LogFileViewer is keyed to the page class, not the route or plugin. The name comes from the page (LogFileViewer), so renaming or subclassing the page changes the permission string Shield generates.php artisan permission:cache-reset for Spatie, and php artisan optimize:clear if config/routes are cached) or you will keep seeing 403s and assume the upgrade is broken.mount() path check with authorization. It validates that the requested file maps to a log path; it was never an access control and still isn't. If you have custom code that assumed mount() gated access, it did not.canAccess() is a fallback, not an override. With Shield installed, granting/denying the permission is authoritative; the closure will not "rescue" a user who lacks the permission.View:LogFileList vs View:LogFileViewer). A user who can see the list but not open entries is the exact symptom of a half-granted role.page_LogFileViewer in a Gate::define (non-Shield setups) rather than patching the page — this is the documented seam and survives upgrades.How can I help you explore Laravel packages today?