5.1 KiB
5.1 KiB
Where Woof — Architecture
How the system ties together, where everything runs, and how data flows.
Systems at a glance
┌─────────────────────────────────────────────────┐
Finder scans tag ──► │ where-woof.com / www / .home.lab (public) │
(QR / NFC → URL) │ Caddy (.35, TLS) ──► .13:3020 │
│ GOAT frontend (Go + HTMX + Alpine + Tailwind) │
│ systemd user service `where-woof` │
└───────────────────┬─────────────────────────────┘
│ same Postgres
┌───────────────────▼─────────────────────────────┐
Staff manage ──► │ admin.where-woof.com / www.admin (staff) │
│ Caddy (.35, TLS) ──► .13:3031 │
│ Laravel + Filament admin (Docker) │
└───────────────────┬─────────────────────────────┘
│
┌───────────────────▼─────────────────────────────┐
│ Postgres 16 `wherewoof-db` (.13:5434) │
│ tables: users, tags, scans, products, orders │
└─────────────────────────────────────────────────┘
- Public path: tag QR/NFC →
where-woof.com/t/<id>→ Caddy on.35→ Go app on.13:3020→ Postgres on.13:5434. Geolocation + alerts send SMS via SMSGlobal HTTP API. - Admin path: staff →
admin.where-woof.com→ Caddy → Laravel/Filament on.13:3031(Docker) → the same Postgres. - Single source of truth: one database, two apps.
db/schema.sqlis canonical (Laravel reads the existing tables via Eloquent; migration ownership moves to Laravel later).
Where things run
| Machine | Role | Runs |
|---|---|---|
| .27 (desktop) | Dev | Go frontend (make run, :3020), Laravel admin (Docker, :3030) — dev copies; build machine for the Go binary |
| .13 (server) | Production | wherewoof-db Postgres (Docker, :5434), frontend (systemd user service where-woof, :3020), Laravel admin (Docker, :3031) |
| .35 (caddy) | Reverse proxy | Caddy — TLS termination for all public domains |
| Router | Public entry | Port-forwards 80/443 → .35; DNS A records → 144.6.86.11 |
| InMotion | DNS/legacy | where-woof.com zone — A records → router IP (legacy site retired) |
Data model (v2 + additions)
users— owners + admins (is_admin),password_hash,remember_tokentags— the registry:tag_code(opaque AES-256-encrypted sequential IDs 0–99), status unset/active/suspended, owner, item details,sms_enabled,product_id,order_idscans— every tag visit: lat/lng,location_shared,scanner_phone,alert_sent,fingerprintproducts— product templates (sku, name, item type)orders— sales: status pending/paid/lapsed/cancelled, linked to tags
Key flows
- Claim: owner registers → adds
tag_code→ must exist in registry (anti-scam) → edits details → statusactive. - Scan: finder opens
/t/<code>→ JS geolocation + fingerprint → POST scan → recorded → alert decision (sms_enabled → fingerprint 24 h block → 10-min/250 m throttle → different-finder rule) → SMS to owner via SMSGlobal HTTP API (pooled/verified number). - Contact: finder leaves number → stored on scan → owner SMS'd (deduped).
- Admin: manage users/tags/products/orders; assign tag → product/order; suspend; dashboard stats.
Security & anti-abuse
- Registry-only tag codes (preset IDs; case-sensitive; no user-created codes).
- Location-aware alert throttle (250 m / 10 min), different-finder re-alert, 24 h device fingerprint block.
- Sessions: signed cookies (Go), Laravel sessions (admin); bcrypt passwords.
- SMS cost protection via the above + per-tag
sms_enabledkill-switch.
Deployment
- Frontend:
make buildon .27 → rsync to.13:/var/www/where-woof→ systemd restart. - Admin: rsync
admin/→.13:/home/sam/Docker/Containers/wherewoof-admin/→docker compose up -d(rebuild image on schema/code change). - Secrets: env-only —
~/.config/where-woof.env(.13 frontend),admin/.env(gitignored). - Docs: see
TOOLS.md(toolchain) andwhere_woof.md(product plan + roadmap).