diff --git a/README.md b/README.md index a37caef..36c4317 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Click **Register** (top right) → name, email, password (≥ 8 characters). You ### 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. +61432374487)**, address, notes, and the *Send me SMS alerts* checkbox. Save → status becomes *Active*. +- 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) diff --git a/frontend/internal/sms/normalize.go b/frontend/internal/sms/normalize.go index 2b16413..7881228 100644 --- a/frontend/internal/sms/normalize.go +++ b/frontend/internal/sms/normalize.go @@ -5,8 +5,8 @@ import "strings" // NormalizeAU normalises a phone number to international AU format without a // leading '+' or zero: // -// "+61432374487" -> "61432374487" -// "0432374487" -> "61432374487" +// "+61423274487" -> "61423274487" +// "0432374487" -> "61423274487" func NormalizeAU(phone string) string { s := strings.Map(func(r rune) rune { if r >= '0' && r <= '9' { diff --git a/frontend/internal/sms/sms_test.go b/frontend/internal/sms/sms_test.go index 16ac28b..16dd516 100644 --- a/frontend/internal/sms/sms_test.go +++ b/frontend/internal/sms/sms_test.go @@ -37,11 +37,11 @@ func TestHaversineMeters(t *testing.T) { func TestNormalizeAU(t *testing.T) { cases := []struct{ in, want string }{ - {"+61432374487", "61432374487"}, - {"0432374487", "61432374487"}, - {"61432374487", "61432374487"}, - {"+61 432 374 487", "61432374487"}, - {"(04) 3237 4487", "61432374487"}, + {"+61423274487", "61423274487"}, + {"0423274487", "61423274487"}, + {"61423274487", "61423274487"}, + {"+61 423 274 487", "61423274487"}, + {"0423 274 487", "61423274487"}, {"", ""}, } for _, tc := range cases { diff --git a/openspec/changes/scan-flow/design.md b/openspec/changes/scan-flow/design.md index 23db081..bd8d371 100644 --- a/openspec/changes/scan-flow/design.md +++ b/openspec/changes/scan-flow/design.md @@ -1,6 +1,6 @@ ## Context -Phase 1 (frontend-foundation, merged) gives us auth, tag setup/management, and the public tag page with `tel:` links. Phase 2 adds the finder-facing scan flow and owner alerts. Confirmed with the owner: SMS provider is **SMSGlobal** (MXT), using their **shared/pooled sender number** (origin blank — upgrade to a registered sender later); real test number `+61432374487`. The `scans` table already exists; it needs no new columns. +Phase 1 (frontend-foundation, merged) gives us auth, tag setup/management, and the public tag page with `tel:` links. Phase 2 adds the finder-facing scan flow and owner alerts. Confirmed with the owner: SMS provider is **SMSGlobal** (MXT), using their **shared/pooled sender number** (origin blank — upgrade to a registered sender later); real test number `+61423274487`. The `scans` table already exists; it needs no new columns. ## Goals / Non-Goals @@ -59,7 +59,7 @@ Phase 1 (frontend-foundation, merged) gives us auth, tag setup/management, and t 1. Re-apply `db/schema.sql` (idempotent ALTER) on the existing dev DB; regenerate sqlc queries. 2. Land code with log sender; run automated suite (no real SMS). -3. Manual check: one real SMS to `+61432374487` with real credentials from `.13`-safe env (local run, then removed). +3. Manual check: one real SMS to `+61423274487` with real credentials from `.13`-safe env (local run, then removed). ## Open Questions diff --git a/openspec/changes/scan-flow/proposal.md b/openspec/changes/scan-flow/proposal.md index ce92c31..7005d8e 100644 --- a/openspec/changes/scan-flow/proposal.md +++ b/openspec/changes/scan-flow/proposal.md @@ -12,7 +12,7 @@ Phase 1 built the foundation (auth, tag setup, public page), but the core produc - **Finder contact**: finder can leave their mobile → stored in `scans.scanner_phone` → owner is SMS'd with the finder's number. - **`sms:` link** on the tag page (prefilled message asking the finder for their number). - **Branding**: "WhereWoof" → **"Where Woof"**, page title **"Where Woof !"** (play on *werewolf*). -- Provider detail (confirmed with owner): SMSGlobal, **pooled/shared sender number** (origin blank; upgrade to registered sender later), real test number `+61432374487`. +- Provider detail (confirmed with owner): SMSGlobal, **pooled/shared sender number** (origin blank; upgrade to registered sender later), real test number `+61423274487`. ## Capabilities diff --git a/openspec/changes/scan-flow/specs/sms-alerting/spec.md b/openspec/changes/scan-flow/specs/sms-alerting/spec.md index 4e3ff02..c4793ff 100644 --- a/openspec/changes/scan-flow/specs/sms-alerting/spec.md +++ b/openspec/changes/scan-flow/specs/sms-alerting/spec.md @@ -41,7 +41,7 @@ SMS sending SHALL go through an abstraction so that automated tests and developm - **THEN** sending an alert logs the message instead of calling the provider ### Requirement: International number format -Phone numbers SHALL be normalised to international format without a leading `+` or leading zero before sending (e.g. `+61432374487` or `0432374487` → `61432374487`). +Phone numbers SHALL be normalised to international format without a leading `+` or leading zero before sending (e.g. `+61423274487` or `0432374487` → `61423274487`). #### Scenario: Number normalisation - **WHEN** an owner or finder number is stored in any local format diff --git a/openspec/changes/scan-flow/tasks.md b/openspec/changes/scan-flow/tasks.md index 5186115..1bc2af4 100644 --- a/openspec/changes/scan-flow/tasks.md +++ b/openspec/changes/scan-flow/tasks.md @@ -23,5 +23,5 @@ - [x] 5.1 Extend the HTTP suite (`/tmp/verify.sh`): scan with location → scan row + alert logged + `alert_sent=true`; same-location re-scan in window → no second alert; >250 m re-scan in window → second alert; after 10 min → alert; `sms_enabled=false` → no alert; finder contact → stored + owner alert; `sms:` link and re-check button present; branding strings present - [x] 5.2 Unit test haversine (known distances) + NormalizeAU cases -- [x] 5.3 Manual real-SMS check to `+61432374487` (real credentials, then removed) +- [x] 5.3 Manual real-SMS check to `+61423274487` (real credentials, then removed) - [x] 5.4 `openspec validate scan-flow`; commit diff --git a/plans/scan-flow.md b/plans/scan-flow.md index 3913e80..07a32de 100644 --- a/plans/scan-flow.md +++ b/plans/scan-flow.md @@ -6,7 +6,7 @@ Plan for OpenSpec change `scan-flow` (proposal/design/specs/tasks in `openspec/c Phase 1 (merged) gives us auth, tag setup/management, and the public tag page with `tel:` links. Phase 2 delivers the core product moment: a finder scans a lost item's tag, the scan (with location when permitted) is recorded, and the **owner is alerted by SMS** (SMSGlobal, pooled sender number) with item type + name, time, maps link, and tag page link. A finder can also leave their number for the owner. Branding: "WhereWoof" → **"Where Woof"** (werewolf wordplay), title **"Where Woof !"**. -All decisions are settled in the change (proposal/design): SMSGlobal REST, **pooled number** (origin blank), real test number **+61432374487**, message includes item type + name (description truncated ~30 chars), finder number stored in `scans.scanner_phone` AND SMS'd to owner, **location-aware throttle** (within 10-min window per tag, re-alert only if new location is >250 m from last alerted location; same spot = recorded, no SMS), and **`sms_enabled` per tag** (some tags are purely informational — default on, toggle on the edit form). +All decisions are settled in the change (proposal/design): SMSGlobal REST, **pooled number** (origin blank), real test number **+61423274487**, message includes item type + name (description truncated ~30 chars), finder number stored in `scans.scanner_phone` AND SMS'd to owner, **location-aware throttle** (within 10-min window per tag, re-alert only if new location is >250 m from last alerted location; same spot = recorded, no SMS), and **`sms_enabled` per tag** (some tags are purely informational — default on, toggle on the edit form). ## Approach @@ -46,11 +46,11 @@ All decisions are settled in the change (proposal/design): SMSGlobal REST, **poo - [x] 6. Tag management: `sms_enabled` checkbox in edit form + handler - [x] 7. Branding sweep: "Where Woof" / "Where Woof !" across templates + README - [x] 8. Extend `/tmp/verify.sh` (scan with/without location, same-spot throttle, >250 m re-alert, post-window alert, `sms_enabled=false`, finder contact, `sms:` link, re-check button, branding); run full suite -- [x] 9. Manual real-SMS check to `+61432374487` (real creds, then remove); `openspec validate scan-flow`; commit +- [x] 9. Manual real-SMS check to `+61423274487` (real creds, then remove); `openspec validate scan-flow`; commit ## Verification -- Unit: haversine known distances; `NormalizeAU` (+61432374487 / 0432374487 → 61432374487). +- Unit: haversine known distances; `NormalizeAU` (+61423274487 / 0432374487 → 61423274487). - HTTP suite (log sender): scan with location → scan row + alert logged + `alert_sent=true`; same-location re-scan within 10 min → recorded, no alert; >250 m re-scan within window → second alert; scan after window → alert; `sms_enabled=false` → no alert; finder contact → stored + owner alert; `sms:` link, re-check button present; button hidden after share; branding strings present. -- Manual: one real SMS to +61432374487 with real credentials. +- Manual: one real SMS to +61423274487 with real credentials. - `openspec validate scan-flow`; commit all.