Laravel producer SDK for the SchoolAid notification pipeline. Apps build immutable, validated payload DTOs and the package handles serialization, Kafka production, and audit logging. It is the single owner of the producer-side contract consumed by the schoolaid-notifications Go service.
Status: 0.1.0, pre-1.0. The payload contract may still change in minor versions.
docs/remains the normative spec; code and contract tests are the source of truth where they overlap.
Today schoolaid-admin re-implements the notification payload shapes inside its message classes (toKafka() methods), which makes the contract implicit, undocumented drift-prone, and impossible to share. This package makes the contract explicit so that:
- marketaid can send notifications without re-implementing anything.
- schoolaid-admin can migrate off its bespoke Kafka plumbing.
- The payload shape is validated at build time and contract-tested against the Go service's JSON Schemas.
| In scope | Out of scope (stays in each app) |
|---|---|
Payload DTOs + builders for note.created, push.batch, email.batch |
Recipient resolution (who gets notified) |
| Build-time validation against the wire contract | Notification templates / localization of content |
| Kafka production (rdkafka), sync and queued | Legacy delivery paths (direct FCM/SMTP from Laravel) |
| Audit logging of every produced message | Retry/backfill business logic (reads the log, app-specific) |
Notifier::fake() test helpers |
Deciding when to notify |
composer require schoolaid/notifierThe service provider and the Notifier facade are registered automatically via package discovery. The notification_logs migration is loaded from the package, so php artisan migrate is enough — publish it only if you need to edit it:
php artisan vendor:publish --tag=notifier-config # config/notifier.php
php artisan vendor:publish --tag=notifier-migrations # optional, to customize the tableKafka production stays off until you set NOTIFIER_ENABLED=true; while disabled, payloads are still built and validated but go to a NullProducer. See docs/configuration.md.
use SchoolAid\Notifier\Facades\Notifier;
use SchoolAid\Notifier\Payloads\NoteCreated\NoteCreatedPayload;
$payload = NoteCreatedPayload::builder()
->note(noteId: 123, schoolId: 45, title: 'Field trip', fromName: 'School Office',
content: '<p>...</p>', important: false)
->channels(['push', 'email'])
->recipient(studentId: 678)
->pushUser(userId: 9, language: 'es', devices: ['fcm-token-1'])
->emailUser(userId: 9, email: 'parent@example.com')
->metadata(userId: 1)
->build(); // throws InvalidPayloadException on contract violation
Notifier::publish($payload); // inline (sync) produce
Notifier::publishAsync($payload); // queued produce- PHP
^8.2 - Laravel
^11.0 | ^12.0 ext-rdkafkaat runtime when Kafka is enabled (suggested dependency, checked lazily)
Everything lives in docs/. If you are an agent maintaining or extending this package, read docs/README.md first — it tells you what to read for the task at hand.