# AGENTS.md — Where Woof (resume brief)

> The **source of truth is `where_woof.md`** (product plan + roadmap) and the **`openspec/` changes**. This file is a quick-resume overview for any agent or session picking the project back up.

## What this is

Where Woof — a **return-tag platform** (not a tracker): pre-coded QR/NFC tags on items; a finder scans → sees return details → owner gets an SMS alert (with finder location when permitted). Branding: "Where Woof !" (werewolf wordplay).

## How we work (the pipeline)

- **Master/worker**: the main pi session (cwd = repo root) orchestrates; subagents do chunks — `database` (schema/queries), `coder-pro` (Go code), `devops-pro` (infra/secrets), `code-analysis` (review). User reviews via plannotator's browser UI when it cooperates; otherwise inline approval.
- Per change: **openspec** (propose → design/specs → tasks, `openspec validate`) → **plannotator** plan (`plans/<name>.md`, submit → approve) → execute with `[DONE:n]` → run `/tmp` verify suites → `code-analysis` review → commit + push to Gitea.
- This is a **learning exercise for the user** — explain decisions, don't just execute.

## Where we are (2026-08-07 EOD)

- **Phase 1 `frontend-foundation` — DONE** (22/22)
- **Phase 2 `scan-flow` — DONE** (19/19 + real SMS via SMSGlobal HTTP API)
- **Phase 2.5 `scan-alert-hardening` — DONE** (12/12: different-finder re-alert + fingerprint 24h block)
- **Phase 3 HTMX/Alpine polish — DONE** (+ tuxedo notes: photo upload, username/email display, favicon)
- **Phase 4 `laravel-admin` — DONE** (Docker Laravel + Filament on .27:3030, shared Postgres, verified)
- **Phase 7 `deploy-frontend` — LIVE on .13** (systemd user service :3020, Caddy blocks saved on .35)
  - ⏳ **Outstanding (user, AM)**: where-woof.com DNS/redirect — A record still at InMotion (173.231.229.92); lab domains use a redirect mechanism (NOT a plain A record — user correction, investigate how both are configured); may involve router/NAT settings
  - Admin (`admin.where-woof.com` → .13:3030) is Phase 8 — nothing runs on 3030 yet
- **Remaining**: Phase 5 billing, Phase 6 photos, Phase 8 admin deploy, Phase 9 hardening

## Key locations

| What | Where |
|---|---|
| Product plan + roadmap (source of truth) | `where_woof.md` |
| OpenSpec specs & changes | `openspec/` (`frontend-foundation` ✅, `scan-flow` ✅) |
| Plannotator plans | `plans/frontend-foundation.md`, `plans/scan-flow.md` |
| Go front-end | `frontend/` (stdlib `net/http`, `internal/{db,auth,handlers,sms}`) |
| Schema | `db/schema.sql` (canonical until Laravel owns migrations) |
| Build/run targets | `Makefile` — `db-up`, `seed`, `run`, `build`, `generate`, `psql` |
| Dev DB | `wherewoof-db` Postgres 16 container on **.13:5434** (user/db `wherewoof`; compose + `.env` in `/home/sam/Docker/Containers/wherewoof-db/` on .13) |
| Run locally | `make db-up && make seed && make run` → `http://localhost:3020` (SMS in **log mode** until creds set) |
| Live frontend | **.13:3020** systemd user service `where-woof` (`/var/www/where-woof`, env `~/.config/where-woof.env`); `where-woof.home.lab` works via .35 Caddy |
| Admin (dev) | **.27:3030** Docker Laravel (`admin/`, Filament) — `cd admin && docker compose up -d`; live deploy = Phase 8 |
| Verify suites | `/tmp/verify.sh` (Phase 1, 22), `/tmp/verify2.sh` (Phase 2, 19), `/tmp/verify3.sh` (hardening, 12) — ephemeral, they reset the DB (incl. admin user — re-seed via `php artisan wherewoof:admin`) |
| Prod target | `.13:/var/www/where-woof` — **frontend LIVE**; admin not yet deployed; Caddy on .35; `where-woof.com` DNS at InMotion (outstanding)
| Gitea | `sam/where_woof` — `ssh://git@gitea.lab.audasmedia.com.au:2222/sam/where_woof.git` |

## Tools

- `openspec` 1.3.1 (spec-driven dev), `plannotator` (plan + browser review), pi subagents (master/worker), `sqlc` 1.31.1 at `~/go/bin` (not on PATH — `make generate` handles it), `pgx` v5, `gorilla/sessions`, `bcrypt`
- **Secrets are env-only, never committed**: `DATABASE_URL`, `SESSION_SECRET`; SMS via **HTTP API** `SMS_USER`/`SMS_PASSWORD`/`SMS_FROM` (proven live 2026-08-07) with REST key/secret (`SMS_API_KEY`/`SMS_API_SECRET`) as unverified fallback
- SMS is a swappable `internal/sms.Sender` — `LogSender` (default) / `smsglobal.Client` (real)

## Gotchas worth remembering

- `.pi/` is gitignored (agent memory + extension tooling are machine-local)
- NixOS box: **no gcc** (`CGO_ENABLED=0` set via `go env -w`), `make` via `nix profile`, no `psql` (use `make psql` → docker exec on .13)
- `html/template` escapes `+` as `&#43;` in hrefs (`tel:`/`sms:` links still work in a browser)
- `pkill -f` can match your own shell — use `pkill -x where-woof`
- Reset the DB between the two verify suites (both bind `TEST000001`)
- Postgres identity columns advance on failed inserts (duplicate-email test consumes an id)
