Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Complete MVP implementation of the Cast GHL Conversation Provider bridge: - Go module setup with chi router and mongo-driver dependencies - Config loading with env var validation and defaults - MongoDB token store with upsert, get, update, delete operations - Cast.ph SMS client with 429 retry logic and typed errors - Phone number normalization (E.164 ↔ Philippine local format) - GHL OAuth 2.0 install/callback/refresh flow - GHL webhook handler with ECDSA signature verification (async dispatch) - GHL API client for message status updates and inbound message stubs - Multi-stage Dockerfile, docker-compose with MongoDB, Woodpecker CI pipeline - Unit tests for phone normalization, Cast client, GHL webhook, and OAuth handlers Co-Authored-By: SideKx <sidekx.ai@sds.dev>
3.0 KiB
3.0 KiB
Task 04: Phone Number Normalization
Objective
Build internal/phone/normalize.go — bidirectional conversion between E.164 and Philippine local format.
Functions
ToLocal — E.164 → Philippine local
func ToLocal(e164 string) (string, error)
| Input | Output | Notes |
|---|---|---|
+639171234567 |
09171234567 |
Standard E.164 |
639171234567 |
09171234567 |
Missing + prefix |
09171234567 |
09171234567 |
Already local, pass through |
9171234567 |
09171234567 |
Missing leading 0 |
+1234567890 |
error | Non-PH country code |
| `` | error | Empty |
abc |
error | Non-numeric |
Rules:
- Strip all non-digit characters (spaces, dashes, parens,
+) - If starts with
63and length is 12: replace63with0 - If starts with
9and length is 10: prepend0 - If starts with
0and length is 11: pass through - Otherwise: return error "invalid Philippine phone number"
- Validate result is exactly 11 digits starting with
09
ToE164 — Philippine local → E.164
func ToE164(local string) (string, error)
| Input | Output | Notes |
|---|---|---|
09171234567 |
+639171234567 |
Standard local |
9171234567 |
+639171234567 |
Missing leading 0 |
+639171234567 |
+639171234567 |
Already E.164, pass through |
| `` | error | Empty |
Rules:
- Strip all non-digit characters except leading
+ - If starts with
+63: pass through - If starts with
63and length is 12: prepend+ - If starts with
0and length is 11: replace0with+63 - If starts with
9and length is 10: prepend+63 - Otherwise: return error "invalid Philippine phone number"
- Validate result matches
+63+ 10 digits
Tests (internal/phone/normalize_test.go)
Test both functions with the table-driven test pattern:
func TestToLocal(t *testing.T) {
tests := []struct {
name string
input string
want string
wantErr bool
}{
{"e164 with plus", "+639171234567", "09171234567", false},
{"e164 without plus", "639171234567", "09171234567", false},
{"already local", "09171234567", "09171234567", false},
{"missing leading zero", "9171234567", "09171234567", false},
{"non-PH number", "+1234567890", "", true},
{"empty", "", "", true},
{"with spaces", "+63 917 123 4567", "09171234567", false},
{"with dashes", "0917-123-4567", "09171234567", false},
{"too short", "0917", "", true},
{"too long", "091712345678", "", true},
}
// ... run tests
}
Same pattern for TestToE164.
Acceptance Criteria
go build ./cmd/server/succeedsToLocalhandles all input formats in the tableToE164handles all input formats in the table- Non-Philippine numbers return error
- Empty strings return error
- Non-numeric input returns error
- Spaces, dashes, parens are stripped
- Results are validated (length + prefix check)
- All tests pass:
go test ./internal/phone/