Sam Rolfe aabaa750f4 Phase 5 billing: account-based annual sub + tag SKUs + SMS pool + tag lifecycle
- Schema: plans, orders subscription cols + plan_id + period_started_at,
  billing_events log, users.stripe_id + sms_credits, products.price_aud
  (db/schema.sql + Laravel migration, idempotent)
- Laravel/Cashier: Billable User, checkout (annual sub + one-off SKUs with
  Managed Payments tax_code), webhook controller (signature-verified,
  idempotent, BILLING_ENABLED kill-switch), account tag transitions,
  nightly reconcile, Stripe portal link, PlanResource + billing dashboard
- Go frontend: account-level gating (paid sub required), SMS pool
  (included 50/yr + credits, drawn after included), plan caps replace
  constants, 60s plan cache (credits fresh), 25-tag cap (plan max_tags)
- BillingSeeder: personal plan + 3 SKUs + dev paid orders
- Verified test-mode e2e: subscribe/paid/active/alerts, pool exhaust +
  credits resume, lapsed/suspended, cancelled/closed, recover/active,
  webhook idempotency, 25-cap, one-off SKUs, replacement, kill-switch,
  invalid signature 400
2026-08-28 13:19:32 +10:00
2026-08-05 10:21:02 +10:00
2026-08-05 10:21:02 +10:00

Where Woof — Return-Tag Platform

Find your woof. A return-item tag platform (PetHub/ReturnMe style) — "Where Woof !" (a play on werewolf). Pre-coded QR/NFC tags on your dog, baggage, skis, etc. A finder scans the tag and sees exactly how to return it — call, text, or leave their number; location is shared with the owner when the finder allows.

Status

GOAT front-end (Phase 1) built and verified — see where_woof.md for the full plan and roadmap.

  • Plan: where_woof.md, awesome-design.md
  • Specs & changes: openspec/ (frontend-foundation ✅, scan-flow ✅)
  • Front-end: frontend/ (Go + HTMX + Alpine + Tailwind + Postgres)
  • Mockups: mockups/

Testing the site (dev)

Everything runs from this repo on .27. SMS is in log mode by default — no real SMS is sent until SMSGlobal credentials are set; instead you'll see SMS to … lines in the server log.

1. Start it

make db-up     # apply schema (idempotent — safe to re-run)
make seed      # insert 25 test tags: TEST000001 .. TEST000025
make run       # http://localhost:3020

2. Create an account (fill in the form)

Click Register (top right) → name, email, password (≥ 8 characters). You're logged in automatically and land on My Tags.

3. Claim a tag (owner side — the form)

  • On My Tags, enter a code like TEST000001 → Add tag. It appears as Unset.
  • Click Edit and fill the form: item type (Dog), description (e.g. Shadow), photo URL, phone number (e.g. +61423274487), address, notes, and the Send me SMS alerts checkbox. Save → status becomes Active.

4. The finder experience (the URL that works)

Open http://localhost:3020/t/TEST000001 in a private/incognito window (that's the finder — no login):

  • It asks for your location → Allow. Watch the server log — an SMS to line appears with the map link.
  • Deny instead → the page still works, and a “Re-check my location” button appears; click it and allow to send the location after all.
  • Send an SMS link → opens your phone's SMS app with the owner's number prefilled.
  • Leave your number → submit a mobile → the owner gets an SMS with the finder's number (also stored on the scan).

5. Throttle behaviour (repeat scans)

  • Scan the same tag at the same location twice within 10 minutes → only one SMS.
  • Scan again from > 250 m away within the window → a second SMS (it moved).
  • Wait 10+ minutes → the next scan alerts again.

6. Info-only tag

Uncheck Send me SMS alerts on the edit form → scans are recorded but no SMS is sent.

7. Watching the SMS

In log mode: tail -f /tmp/ww-server.log and look for SMS to. With real credentials set, the owner's phone receives the text — set SMS_USER/SMS_PASSWORD/SMS_FROM (SMSGlobal HTTP API, from = your verified number like 61423274487) when running make run.

Notes

  • Geolocation requires HTTPS except on localhost — testing on a phone over the LAN needs the Caddy/TLS deployment (Phase 7) or localhost.
  • Reset the database any time: make db-up re-applies the schema (idempotent); drop the wherewoof-db container volume for a truly fresh start.
  • Automated suites live in /tmp/verify.sh (Phase 1, 22 checks) and /tmp/verify2.sh (Phase 2, 19 checks) — they reset the DB themselves.
Description
No description provided
Readme 12 MiB
Languages
PHP 38.7%
Blade 23.8%
Go 23.3%
HTML 13.3%
Makefile 0.4%
Other 0.5%