sam-4screen-desktop 2026-9-6:8:39:8

This commit is contained in:
2026-09-06 08:39:08 +10:00
parent e1bb4a558f
commit e70062dbba

View File

@@ -1,41 +1,66 @@
# Where Woof # Where Woof
> Return-tag platform: QR/NFC tags on valuables; finder scans → owner gets SMS with map link. Go + HTMX frontend, Laravel/Filament admin, shared Postgres. > Return-tag platform: QR/NFC tags on valuables; finder scans → owner gets SMS with map link. Go + HTMX frontend, Laravel/Filament admin, shared Postgres, Stripe AU billing.
## Project state (2026-08-28) ## One-line
**Live:** frontend `where-woof.com` (.13:3020) · admin `admin.where-woof.com` (.13:3031) Every valuable deserves a way home: a $5 tag, a $10/yr account, and when the tag is scanned you get an SMS with the finder's map link.
**Phases done:** foundation, scan flow (real SMS via SMSGlobal), hardening, HTMX polish, admin, deploy, **billing (Phase 5)** — account-based annual sub. ## Where things live (the 5 tools)
## Billing model (locked with owner) | Tool | What it holds | Where |
|---|---|---|
| **Gitea** | Source + git history | `sam/where_woof` — ssh://git@gitea.lab.audasmedia.com.au:2222/sam/where_woof.git |
| **Vikunja** | Project tasks, done/todo, priorities | Project **"Where Woof"** (id 7) — vikunja.lab.audasmedia.com.au |
| **Outline** | Project docs for AI bots (overview, architecture, configs, schema, status) | Collection **"Where Woof"** — outline.lab.audasmedia.com.au |
| **Obsidian** | This note — human understanding | 200 projects / 240 Web Sites / Where Woof.md |
| **OpenSpec** | Change proposals (proposal/design/specs/tasks) + plans | `openspec/changes/*` + `plans/*.md` in repo |
- **Account = the product**: $10/yr flat, up to **25 tags**, **50 SMS/yr included**; extra SMS $0.10 each (100-credit pack = $10). **How they relate:** Vikunja = *what to do* (tasks). Outline = *what/why/how* for AI agents. Obsidian = *human brain* reference. OpenSpec = *design decisions* per feature. Gitea = *the code itself*.
- **Tags one-time**: single **$5 + GST** ($5.50), 10-pack **$20 + GST** ($22.00). Cost ~$1 to make.
- **Replacement tags**: new SKU $5 one-time, annual sub continues untouched. Move mechanic already built (source→closed, unset target→active). ## Status (2026-09-05)
- **Business/public-info model deferred** (scan-volume tiers, no SMS) — `plans.plan_type='business'` reserved.
- Sandbox-first: Stripe test mode verified e2e; live keys pending onboarding. - **LIVE**: frontend where-woof.com (.13:3020) · admin admin.where-woof.com (.13:3031)
- **Done**: phases 1–8 + billing (Phase 5) + promo (order page, banner, contact form)
- **Blocking**: Stripe **go-live** (test mode only now — no real sales) · SES production access + incoming hello@ routing
## Billing model (locked)
- **Account = the product**: $10/yr flat, up to **25 tags**, **50 SMS/yr included**; extra SMS $0.10 (100-credit pack = $10).
- **Tags one-time**: single **$5 + GST** ($5.50) · 10-pack **$20 + GST** ($22.00). Cost ~$1/tag to make.
- **Replacement tags**: new SKU $5 one-time, annual sub continues untouched.
- **Business/public-info deferred**: `plans.plan_type='business'` reserved (scan-volume tiers, no SMS).
## Stack / infra ## Stack / infra
- Frontend: Go `net/http`, sqlc/pgx, HTMX/Alpine/Tailwind. Admin: Laravel 13 + Filament 3 + Cashier 16 (Stripe AU). - **Frontend**: Go `net/http`, sqlc/pgx, HTMX/Apline/Tailwind — `.13:3020` systemd user service.
- Shared Postgres on .13:5434 (`wherewoof`), schema canonical in `db/schema.sql`. - **Admin**: Laravel 13 + Filament 3 + Cashier 16 (Stripe AU) — `.13:3031` Docker.
- Deploy: per-file `rsync --checksum` to .13 + systemd/docker restart. Gitea `sam/where_woof`. - **DB**: Postgres `.13:5434` (`wherewoof`), schema canonical `db/schema.sql`.
- SMS: SMSGlobal HTTP API (`SMS_USER/PASSWORD/FROM`) — **live creds are set on .13**. - **SMS**: SMSGlobal HTTP API — **live creds set on .13** (`SMS_USER/PASSWORD/FROM`).
- Email: Gmail SMTP → samuelrolfe@gmail.com (app password, env-only). hello@where-woof.com = public contact (Cloudflare/SES planned). - **Email**: Amazon SES (ap-southeast-2) transactional only, sends as `hello@where-woof.com`, contact form → samuelrolfe@gmail.com. **Sandbox** until production access approved.
- **Storage**: MinIO on .13:9010 for tag photos.
- **Ordering**: Stripe Payment Links (test mode) on `/order`.
## Promo (2026-08-28) ## Key configs (env-only, never committed)
- `/order` page with Stripe Payment Links (test mode): single 1–25 qty, 10-pack 1–2. - `.13 ~/.config/where-woof.env` — frontend: DATABASE_URL, SMS_*, SMTP_*, STRIPE_*, ORDER_*_LINK, BILLING_ENABLED, SMS_INCLUDED_PER_YEAR
- Red banner across all pages: "Protect & recover your valuables — ORDER NOW". - `.13 ~/Docker/Containers/wherewoof-admin/.env` — admin: DB_*, STRIPE_* (test), CASHIER_CURRENCY
- Contact form → Gmail SMTP. - **Secrets live only on .13 — never paste into chat or commit.**
## Gotchas ## Gotchas
- Laravel login: `User::$authPasswordName = 'password_hash'` (Laravel 13 rehash-on-login writes the wrong column otherwise). - Laravel login: `User::$authPasswordName = 'password_hash'` (Laravel 13 rehash-on-login).
- Cashier: Managed Payments requires `tax_code` → `txcd_10103001` (SaaS) is eligible. - Cashier/Stripe: Managed Payments needs `tax_code` → `txcd_10103001` (SaaS) — Tangible Goods rejected.
- curl `-F "phone=%2B..."` stores literal `%2B` — use real `+`. - curl `-F "phone=%2B..."` stores literal `%2B` — use real `+`.
- Vikunja token intermittently 401s — retry once.
- Outline public API returns 502 (Caddy route missing) — use `http://192.168.20.13:3000/api` directly.
## Next up (see Vikunja project 7)
1. **GO LIVE Stripe** (urgent — blocks real sales)
2. SES production approval + Cloudflare Email Routing (incoming hello@)
3. Photo uploads (Phase 6), anti-abuse (Phase 9), customer insights dashboard
## Links ## Links
- [[210 AI Resume]] · [[220 Web Host Migration]] · [[240 Web Sites]] [[210 AI Resume]] · [[220 Web Host Migration]] · [[240 Web Sites]] · [Vikunja: Where Woof](https://vikunja.lab.audasmedia.com.au) · [Outline: Where Woof](https://outline.lab.audasmedia.com.au)