spokospace/filament-ops-notify
spokospace/filament-ops-notify is a Laravel/Filament package that adds operational notifications to admin panels, helping teams surface alerts, status updates, and system events directly in the dashboard so issues are noticed, triaged, and handled faster without leaving the panel.
What this is. A Laravel package for operational alerting: a facade-style sender (OpsMessage::send()), a custom ops notification channel that plugs into Laravel's notification system, a burst guard (per-event, per-destination rate limiting), a digest that reports suppressed volume, a chat-destination layer with a paged discovery scan, and a Filament-style panel plus an artisan command (ops-notify:test) for operator self-service. It sits on the critical path of business events — the release notes explicitly name "saving an inquiry" and "finishing a build" as the host requests that could be affected.
Architecture fit. The package is well-behaved Laravel: it uses the cache for dedupe/burst state, the queue for digest and resend work, the scheduler for digest timing, and the DB for the suppressed-row log. That is idiomatic, but it means the package inherits the failure characteristics of every one of those subsystems. The most important architectural property of v1.3.1 is that it is now fail-open on the alerting path: an unreachable cache degrades to "log and send anyway" rather than throwing into the host request. For a package whose blast radius previously included 500s on unrelated user actions, this is the single most valuable change in the release.
Integration feasibility. Very low friction. No config changes, no migrations, no breaking changes for normal use. The one internal API change — BurstGuard::pullHeld() replaced by heldCount() + clearHeld() — matters only if our application (or another package) has subclassed, decorated, or reflected into BurstGuard. That is checkable in minutes and should be a pre-merge grep, not a design discussion.
Technical risk.
Failed instead of a false "Queued", and ops-notify:test --queue returns non-zero when nothing was queued. Both are improvements; both will look like a regression to whoever wrote a runbook around the old output.Key questions.
BurstGuard treated as internal by the maintainer, and does anything in our codebase or our other packages extend it?Cache::add + increment atomicity and TTL re-arming; Redis and Memcached are the safe assumptions, and we should confirm the database cache driver is either supported or explicitly out of scope.Stack fit. Assumes a conventional Laravel deployment: queue worker, scheduler, cache, DB, plus Horizon for the panel's status widget. No new services are introduced by this release. The package is a leaf dependency — nothing else depends on it — which keeps the integration boundary clean.
Migration path. Treat as a routine dependency bump: update the constraint, composer update, deploy. No migration step, no config republish, no cache flush strictly required — though flushing the burst/digest keyspace is harmless and gives a clean baseline for the changed key shape. The only pre-merge gate is the pullHeld() grep. If it comes back clean, this is a one-line change and a pipeline run.
Compatibility. No breaking changes for normal use, per the maintainer. The residual compatibility surface is the burst-key shape (behavioural, not API), the discovery lock duration (infrastructure, not code), and the panel's resend status semantics (operator-visible). None of these are compile- or boot-time concerns.
Sequencing.
pullHeld() / BurstGuard extension points; clear the internal-API gate.ops-notify:test --queue and confirm exit code 0 in the pipeline; confirm a non-zero exit when the queue is deliberately unreachable.Failed with its button when the resend is burst-held — i.e. verify the honest-status behaviour an operator now depends on.Rollback. Clean, because there is no schema or config delta. Reverting the constraint restores prior behaviour, with the caveat that in-flight burst counters carry the new destination-scoped keys and will look like cold keys to the old version, temporarily letting suppressed volume through. Acceptable for a reliability-only release; worth stating rather than discovering.
Maintenance. Low and decreasing. The package appears actively maintained — this release is the output of a full src/ review, which is a good signal of maintainer attention rather than a one-off patch. The 285-test suite with Larastan level 8 gives reasonable regression confidence for a package of this size, and the release notes are unusually specific about root cause, which lowers the cost of future incident diagnosis.
Support. Support burden shifts decisively in our favour with this release. Two classes of tickets go away: "the app 500'd while saving an inquiry because alerts broke", and "the panel said Queued but nothing was sent". Both were the kind of bug that erodes trust in the alerting system and, by extension, in the panel. The honest Failed state and the meaningful exit code on ops-notify:test --queue also mean we can assert on alerting health in CI rather than discovering it in production.
Scaling.
Failure modes, post-upgrade.
Ramp-up. Minimal for developers — no new concepts, no config. The ramp-up burden is on operators, in two small ways: the resend button's behaviour is now truthful and therefore sometimes stays Failed (expect one round of "why didn't it queue?"), and multi-destination events may alert more often than the previous baseline. A short note in the runbook covering the honest resend state, the ops-notify:test --queue exit-code check, and the expectation of duplicates during a cache incident covers essentially all of it.
Recommendation. Upgrade. This release removes a production-availability defect that reached past the alerting subsystem into unrelated user-facing requests — the highest-value class of fix a package like this can ship. The cost is one grep, one worker-timeout check, and a brief re-baseline of alert volume for fanned-out events.
How can I help you explore Laravel packages today?