Notification & Alert System (Stub)
Notification & Alert System (Stub)
Status: Stub – v0.1 Audience: Backend engineers Purpose: Outline the minimal notification pipeline required for early MVP, focused on scan events for lost / stolen objects. Will be expanded later to cover push, in-app, and SMS.
1. Trigger Matrix
| Event Source | Conditions | Recipients | Channel | Notes |
|---|---|---|---|---|
ScanEvent |
Object has status lost, stolen, missing OR ACL indicates owner cannot currently see it |
Current owner (users.email), org admins |
Email (Resend) | Include timestamp & geolocation from scan payload |
StatusUpdate |
Status changes to lost or stolen |
Owner, org admins | First alert when item is flagged | |
(future) OfferAccepted |
Marketplace offer accepted | Buyer & seller | Email + push | — |
2. Email Transport – Resend
2.1 API Key Storage
- Use Supabase encrypted secrets feature or env var
RESEND_API_KEYin serverless function.
2.2 Helper Function (pseudo-code)
import { Resend } from 'resend'
export async function sendEmail(to: string, subject: string, html: string) {
const resend = new Resend(process.env.RESEND_API_KEY)
await resend.emails.send({
from: 'Plings <alerts@plings.io>',
to,
subject,
html,
})
}
2.3 Template – Lost/Stolen Scan
<h1>Heads-up: Your item was scanned</h1>
<p>Item: <strong></strong></p>
<p>When: </p>
<p>Where: </p>
<p>If you've recovered the item, you can update its status in the app.</p>
3. Backend Flow Stub
- GraphQL resolver
resolveIdentifier→ once it classifies the tag as KNOWN_OBJECT: - Internal call
recordScanEvent(objectId, userId, geo)(done today). - Add step:
if (object.statuses.includes('lost') || object.statuses.includes('stolen')) { queueEmailNotification('lost_stolen_scan', { objectId, ownerId, geo, ts }) } queueEmailNotificationwrites tonotifications_outboxtable. A background worker (cron or Supabase function) polls this table and sends via Resend.
4. Database Tables (initial)
-- audit_log_system already stores scans; add minimal outbox
create table if not exists notifications_outbox (
id uuid primary key default gen_random_uuid(),
type text not null, -- e.g. 'lost_stolen_scan'
payload jsonb not null,
created_at timestamptz default now(),
sent_at timestamptz
);
5. GraphQL Types (to add later)
type Notification {
id: ID!
type: String!
payload: JSON!
createdAt: DateTime!
sentAt: DateTime
}
6. Open Items
- Decide on push vs email prioritisation.
- Rate-limit notifications if a lost item is scanned repeatedly.
- Owner contact workflow: secure chat vs masked email relay.
- GDPR / data-retention policy for outbox table.