Add comprehensive project documentation and architecture guidelines
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled

Establishes core rules and conventions for the FuelAlert Laravel application: architecture patterns (fat services, thin controllers), database schema with partitioned station_prices table, multi-tier notification system with Vonage and OneSignal, 4-signal scoring engine for fuel price recommendations, Stripe subscription tiers, Livewire classic component structure, and Pest testing standards.
This commit is contained in:
Ovidiu U
2026-04-03 16:49:19 +01:00
parent c94c4f7beb
commit 02d4c9d888
11 changed files with 644 additions and 0 deletions

68
notifications.md Normal file
View File

@@ -0,0 +1,68 @@
# Notifications
## Tier-to-channel mapping
| Tier | Price | Email | Push (PWA) | WhatsApp | SMS |
|------------|--------|-------|------------|----------|-----------|
| Free | £0 | ✓ weekly digest | ✗ | ✗ | ✗ |
| Basic | £0.99 | ✓ daily | ✓ daily | ✓ daily | ✗ |
| Plus | £2.49 | ✓ | ✓ | ✓ | ✓ max 1/day triggered |
| Pro | £3.99 | ✓ | ✓ | ✓ | ✓ max 3/day triggered |
## NotificationDispatchService
Reads user tier via Cashier, returns allowed channels:
```php
public function channelsFor(User $user): array
// Returns e.g. ['mail', 'vonage-whatsapp'] for Basic tier
// Returns ['mail', 'vonage-whatsapp', 'vonage-sms'] for Plus+
```
Never fire SMS unless confidence ≥ 70 AND user is Plus/Pro.
Never fire more than 1 notification per user per day unless they are Pro tier.
Log every sent notification to `alerts` table.
## Laravel Notification class
One `FuelPriceAlert` notification class with `via()` returning channels based on tier.
Subject line / message copy adapts based on `recommendation` and `confidence`.
## WhatsApp (Vonage)
- Provider: Vonage Messages API (WhatsApp channel)
- PHP package: `vonage/client`
- Template: utility category (one-way alert) — pre-approved template required by Meta
- Opt-in: phone number + OTP flow (see otp_verifications table)
- User must have `whatsapp_verified_at` set — never send to unverified numbers
- Cost: ~0.30.5p per message (utility rate)
- Message format: keep under 160 chars. Include station name, price, and recommendation reason.
## SMS (Vonage — Plus/Pro only)
- Same Vonage client, SMS channel
- Triggered only (not daily) — fires when signal strength ≥ 2 AND price event warrants it
- Plus: max 8 SMS/month (enforced via alerts table count)
- Pro: max 30 SMS/month
- Cost: ~3.5p per message UK
## Email
- Driver: Mailgun (configured in .env)
- Free tier: weekly digest every Monday 8am
- Basic+: daily summary if recommendation is not `no_signal`
- Use Mailable classes, not raw Mail::send
- Templates in `resources/views/emails/`
## Push notifications (OneSignal)
- Free plan: up to 10,000 subscribers
- Player ID stored in `users.push_token`
- Use OneSignal REST API — no official Laravel package needed, simple HTTP call
- PWA service worker setup required (separate task)
- Basic+: daily push alongside email
## Queue
All notifications are dispatched as queued jobs — never send synchronously.
Use `FuelAlertNotificationJob` dispatched per user.
Queue: `notifications` (separate from default queue for priority control).