Yard StudioJamaica-first · scam-skeptical
Back to Hearthline

Hearthline — Technical Specification

Constraint file: `../JAMAICA_TRUST.md` Launch geography: Jamaica (island household) + diaspora viewers (US/UK/Canada). Stack: Progressive Web App (Next.js), on-device/private extraction, WhatsApp share, no payment required for the radar.


System architecture

[Android/iOS/Desktop browser]

HTTPS, service worker

v [Hearthline PWA] - Camera capture (getUserMedia) - Local draft store (IndexedDB, encrypted at rest) - Last-radar cache (Cache Storage)

+---> [Extract worker] vision+layout model

on-device when possible;
else private-cloud in a Jamaica-or-CARICOM-preferring region

+---> [API: households, intervals, share-links]

+---> [WhatsApp] user-initiated share of PNG/PDF only

X---> JPS / bank / remittance APIs (forbidden) X---> Helper marketplace checkout (forbidden)

Trust boundary: the island household is the data controller. Diaspora “Circle” is read-only unless the household grants a named action (e.g. “mark pharmacy done”). Remittance never enters this system.


Core APIs (v1)

All routes are versioned /v1. Auth is WebAuthn or a WhatsApp-otp-to-phone on the island number, not email-and-password theatre.

MethodPathPurpose
POST/householdsCreate household (display name + parish). No card.
POST/evidenceUpload compressed image (multipart). Server stores only after client-side redaction option (cover address).
POST/evidence/{id}/extractReturn draft Interval[]. Never auto-commit.
PUT/intervals/{id}Confirm, correct, assign owner, mark done/skipped/unsure.
GET/radar?hours=4Confidence-weighted intervals for the polar UI.
POST/sharesCreate a time-boxed view link (default 72h, revocable). Returns a PNG *and* a URL.
POST/shares/{id}/revokeKill the link.
GET/receiptsPlain-language log (Data Protection Act access).
POST/exportZIP of photos + intervals (household portable record).
DELETE/households/{id}Tombstone + purge within 30 days.

Explicitly absent: /payments, /helpers/book, /portal/login, /lynk.


Data models

type Parish =

"Kingston""St. Andrew""St. Thomas""Portland""St. Mary"
"St. Ann""Trelawny""St. James""Hanover""Westmoreland"
"St. Elizabeth""Manchester""Clarendon""St. Catherine";

interface Household { id: string; name: string; parish: Parish; controllerPhoneE164: string; // +1876... createdAt: string; }

interface Evidence { id: string; householdId: string; kind: "discharge" | "script" | "label" | "note" | "other"; blobRef: string; capturedAt: string; capturedOffline: boolean; }

interface Interval { id: string; householdId: string; action: string; windowStart: string; windowEnd: string; confidence: number; // 0..1, first-class blastRadius: "low" | "high"; ownerMemberId: string | null; status: "draft" | "confirmed" | "done" | "skipped" | "unsure"; evidenceIds: string[]; }

interface ShareLink { id: string; householdId: string; expiresAt: string; canMarkDone: boolean; revokedAt: string | null; }

No TRN stored in v1. Optional parish badge is a later table, never a login requirement.


Security framework

  • TLS 1.3 only. HSTS.
  • Encryption at rest (AES-256) for evidence blobs; envelope keys per household.
  • No vendor training on household photos. Contractual + technical (separate inference account).
  • Data Protection Act, 2020: privacy notice in plain English; lawful basis = household consent; access, correction, deletion, portability in-product.
  • Share links are capability tokens, not guessable IDs; rate-limited; watermarked PNG (“for family WhatsApp — not a payment page”).
  • Threat we design for: a fake Hearthline site that asks for Lynk. Our real origin is pinned in the 876 voicemail and on the partner-desk card.
  • HIPAA is not Jamaica law; we still treat health photos as special category data.
  • CSP, no third-party ad pixels, no Facebook SDK.

PWA specification (universal + Jamaica)

ItemSpec
Manifestname: Hearthline, display: standalone, start_url: /radar, orientation: any
Icons192 / 512 maskable; no “download APK” link anywhere
Service workerPrecache shell; cache last radar + last 3 evidence thumbs
Background syncQueue evidence uploads when Digicel/FLOW returns
Cameracapture=environment on file input as fallback if getUserMedia blocked
StorageBudget for low-end Android; evict oldest thumbs first
A11y48px targets, 1.4 line-height, works at 200% zoom
Support chromePersistent footer: +1 876 … · parish desk hours

Scalability plan

  • Year 0: single region, 10k households, object storage + Postgres.
  • Extract is async; a household of 6 does not need a GPU farm.
  • Diaspora viewers are cheap (read replicas + CDN for share PNGs).
  • If a public hospital ever offers FHIR, it is an optional connector behind the same confirm step — never the launch path.

What we will not integrate at launch

MyChart, Stripe-only checkout, crypto wallets, helper gig marketplaces, remittance APIs that would let us “collect for Mummy.”