Head of Product & Engineering a40a4aa626
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
feat: initial implementation of Cast GHL Provider
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>
2026-04-04 17:27:05 +02:00

120 lines
2.6 KiB
Markdown

# Task 01: Project Initialization
## Objective
Set up the Go project, directory structure, go.mod, and placeholder files.
## Steps
### 1. Initialize Go module
```bash
go mod init github.com/nicknacnic/cast-ghl-provider
```
(Adjust module path to match your Gitea repo at git.sds.dev)
### 2. Install dependencies
```bash
go get github.com/go-chi/chi/v5
go get go.mongodb.org/mongo-driver/v2/mongo
```
### 3. Create directory structure
```
cmd/server/main.go # placeholder: log.Println("cast-ghl-provider starting...")
internal/config/config.go # placeholder: package config
internal/ghl/oauth.go # placeholder: package ghl
internal/ghl/webhook.go # placeholder
internal/ghl/api.go # placeholder
internal/ghl/types.go # placeholder
internal/cast/client.go # placeholder: package cast
internal/cast/types.go # placeholder
internal/phone/normalize.go # placeholder: package phone
internal/store/mongo.go # placeholder: package store
```
### 4. Create `.env.example`
```env
PORT=3002
BASE_URL=https://ghl.cast.ph
# GHL OAuth
GHL_CLIENT_ID=
GHL_CLIENT_SECRET=
GHL_WEBHOOK_PUBLIC_KEY=
GHL_CONVERSATION_PROVIDER_ID=
# Cast.ph
CAST_API_KEY=
CAST_API_URL=https://api.cast.ph
CAST_SENDER_ID=
# MongoDB
MONGO_URI=mongodb://localhost:27017/cast-ghl
# Inbound (Phase 2)
INBOUND_API_KEY=
```
### 5. Create `.gitignore`
```
.env
cast-ghl-provider
/tmp/
```
### 6. Create `Dockerfile` (placeholder)
```dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /cast-ghl-provider ./cmd/server/
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /cast-ghl-provider /cast-ghl-provider
EXPOSE 3002
CMD ["/cast-ghl-provider"]
```
### 7. Create `docker-compose.yaml`
```yaml
services:
bridge:
build: .
ports:
- "${PORT:-3002}:${PORT:-3002}"
env_file: .env
depends_on:
- mongo
restart: unless-stopped
mongo:
image: mongo:7
volumes:
- mongo-data:/data/db
restart: unless-stopped
volumes:
mongo-data:
```
### 8. Copy API reference docs
- Copy `CAST_API_REFERENCE.md` into repo root (from the Cast API docs provided)
- Create `GHL_API_REFERENCE.md` with the GHL Conversation Provider docs
### 9. Verify
```bash
go build ./cmd/server/
go vet ./...
```
## Acceptance Criteria
- [ ] `go build ./cmd/server/` succeeds
- [ ] `go vet ./...` passes with no issues
- [ ] All packages have at least a placeholder file
- [ ] `.env.example` has all config vars documented
- [ ] `Dockerfile` builds successfully
- [ ] `docker-compose.yaml` is valid
- [ ] `.gitignore` excludes `.env` and binary